Return statement and whitespace

G

Gabriel Gilini

I've just realized, looking at this "JavaScript compressor"[1] output,
that, at least in Firefox 3.0.4, the whitespace(s) between the return
statement and the expression that succeeds it is optional.

Meaning that -

function foo(){
return'bar';
}
foo();

- is a valid JavaScript program.

I looked at the specifications (The return Statement - session 12.9)
and couldn't find anything specific on this subject.

So, is this true for every other modern browser? And if yes, it's kind
of a quirk, isn't it?

[1] http://www.xorax.info/labs/jsxs/

Regards
 
G

Gabriel Gilini

Gabriel said:
I've just realized, looking at this "JavaScript compressor"[1] output,
that, at least in Firefox 3.0.4, the whitespace(s) between the return
statement and the expression that succeeds it is optional.
Meaning that -
function foo(){
   return'bar';
}
foo();
- is a valid JavaScript program.
I looked at the specifications (The return Statement - session 12.9)
and couldn't find anything specific on this subject.

"The return Statement" doesn't say anything about required whitespace;
It only disallows /LineTerminator/ in between `return` keyword and
following expression.
QED

 From what I can see, a whitespace can be omited from return statement
as long as overall production is unambiguous.

For example, look at `return1` and `return'foo'`. Former production
becomes a plain identifier (`return1`) and would result in
ReferenceError (unless `return1` is declared before), while latter one
can be unambiguously parsed as return keyword, followed by string
literal. I think the latter one is parsed due to "'" character (that's
immediately after "return") not being able to be part of a keyword or
identifier.

So, as I see, anything that is not part of an identifier or keyword
could be 'trimmed' by a compressor to save some bytes.
Other examples of unambiguous productions with no whitespace are:

return(1);
return/**/1;
return/1/;
return.1;
return-1;
return+1;

var x = 2;
(function(){ return--x; })(); // 1
(function(){ return++x; })(); // 3

I probably missed something else.

Irrelevant, you made your point.
I don't think it's a quirk, but I'm not completely sure myself about the
rules for these productions.

Sure, because they aren't really defined.
Personally, I'd rather not trust anything as dubious as this.
 
G

Gabriel Gilini

So, as I see, anything that is not part of an identifier or keyword
could be 'trimmed' by a compressor to save some bytes.

I probably wasn't as clear as I wanted, so let me rephrase that.

It looks like that anything that comes right after a return Statement
(an Expression) can be trimmed, as long as it doesn't start with an
identifier-valid character. Although, as I said earlier, I'd rather
not trust it, as it's not explicitly mentioned in the specification.
 
N

NickFitz

Sure, because they aren't really defined.
Personally, I'd rather not trust anything as dubious as this.

They are very clearly defined in the ECMA-262 ECMAScript Language
Specification, which can be downloaded from:
<http://www.ecma-international.org/publications/standards/
Ecma-262.htm>

Understand that document in its entirety, and you will realise that
there is nothing "dubious" about those productions. They are
syntactically well-formed code (although not conducive to legibility).

Regards,

Nick.
 
R

Richard Cornford

They are very clearly defined in the ECMA-262 ECMAScript Language
Specification, which can be downloaded from:
<http://www.ecma-international.org/publications/standards/
Ecma-262.htm>

Understand that document in its entirety, and you will realise
that there is nothing "dubious" about those productions. They
are syntactically well-formed code (although not conducive to
legibility).

A particularly pertinent part of the specification may be the opening
paragraph of section 7, which reads:-

| The source text of an ECMAScript program is first converted into
| a sequence of input elements, which are either tokens, line
| terminators, comments, or white space. The source text is scanned
| from left to right, repeatedly taking the longest possible
| sequence of characters as the next input element.

It is the requirement to take "the longest possible sequence of
characters" that means that:-

returnX

- will always be a single Identifier token and never a ReservedWord
token followed by an Identifier token (as defined in section 7.5).

Richard.
 
T

Thomas 'PointedEars' Lahn

Gabriel said:
I've just realized, looking at this "JavaScript compressor"[1] output,
that, at least in Firefox 3.0.4, the whitespace(s) between the return
statement and the expression that succeeds it is optional.

Meaning that -

function foo(){ return'bar'; } foo();

- is a valid JavaScript program.

I looked at the specifications (The return Statement - session 12.9) and
couldn't find anything specific on this subject.

Obviously you have not searched for "white space":

| 7.2 White Space
|
| White space characters are used to improve source text
| readability and to separate tokens (indivisible lexical units)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| from each other, but are otherwise insignificant. White space
| may occur between any two tokens, and may occur within strings
^^^
| (where they are considered significant characters forming part
| of the literal string value), but cannot appear within any
| other kind of token.
|
| The following characters are considered to be white space:
| [...]


PointedEars
 
D

Dr J R Stockton

In comp.lang.javascript message <a8e1a2dc-8858-4bcb-80a6-3063180e23cb@o1
5g2000yqm.googlegroups.com>, Thu, 23 Jul 2009 18:25:44, Gabriel Gilini
I've just realized, looking at this "JavaScript compressor"[1] output,
that, at least in Firefox 3.0.4, the whitespace(s) between the return
statement and the expression that succeeds it is optional.

Consider the following, and what it does in Firefox 3.0.11 and other
systems -

function A() alert(1) ; alert(2)
A() ; A()

That, to my mind, rather proves that (as you implicitly acknowledge) a
single browser cannot be used to determine reliably whether any
particular code is correct for all browsers.
 
J

John G Harris

Consider the following, and what it does in Firefox 3.0.11 and other
systems -

function A() alert(1) ; alert(2)
A() ; A()

That, to my mind, rather proves that (as you implicitly acknowledge) a
single browser cannot be used to determine reliably whether any
particular code is correct for all browsers.

In an ideal universe every javascript parser would say syntax error. In
practice, programmers get pay rises and promotion for not handling cases
that don't happen very often, so there may be browsers that do something
with this code. To guess what they will do you would have to consult the
browser documentation (big laugh) as it's outside the agreed common
standards.

John
 
J

John G Harris

I've just realized, looking at this "JavaScript compressor"[1] output,
that, at least in Firefox 3.0.4, the whitespace(s) between the return
statement and the expression that succeeds it is optional.

Meaning that -

function foo(){
return'bar';
}
foo();

- is a valid JavaScript program.
<snip>

Have you never wondered about
v=a+b;
as opposed to
v = a + b;

John
 
L

Lasse Reichstein Nielsen

Gabriel Gilini said:
I've just realized, looking at this "JavaScript compressor"[1] output,
that, at least in Firefox 3.0.4, the whitespace(s) between the return
statement and the expression that succeeds it is optional.

Whitespace has no intrinsic meaning, all it does is to separate tokens
(except newline in the case of semicolon-insertion). The parser
ignores whitespace.
Meaning that -

function foo(){
return'bar';
}
foo();

- is a valid JavaScript program.
Correct.

I looked at the specifications (The return Statement - session 12.9)
and couldn't find anything specific on this subject.

Whitespace is removed during tokenization, i.e. when "return" is
recognized as a keyword and "'bar'" as a string literal. Any whitespace
between the two is discarded there and the parser only sees the return
keyword and the string literal.
So, is this true for every other modern browser?

It should be. It's what the specification requires.
And if yes, it's kind of a quirk, isn't it?

No.
No more than the whitespace in "x + 2" is optional, and "x+2" means
the same thing.

/L
 
D

Dr J R Stockton

In comp.lang.javascript message <[email protected]
8924D9443D28E23ED5CD>, Sat, 25 Jul 2009 17:34:11, John G Harris
In an ideal universe every javascript parser would say syntax error. In
practice, programmers get pay rises and promotion for not handling cases
that don't happen very often, so there may be browsers that do something
with this code. To guess what they will do you would have to consult the
browser documentation (big laugh) as it's outside the agreed common
standards.

Browser documentation tells at best what the documenter thought the
browser would or should do. It is no substitute for actual test. To
illustrate that point, compare what the JScript documentation says about
0.007.toFixed(2) and what IE does.

<FAQENTRY> ISTM that Section 5.1 paragraph 4 needs
correction : for 0.07 read 0.007. </FAQENTRY>

Firefox 3.0.11 & 3.0.12 give three alerts, 2 1 1. Other browsers don't
like the syntax.
 
J

John G Harris

In comp.lang.javascript message <[email protected]
8924D9443D28E23ED5CD>, Sat, 25 Jul 2009 17:34:11, John G Harris


Browser documentation tells at best what the documenter thought the
browser would or should do. It is no substitute for actual test.

A programmer who relies on any particular non-standard behaviour is
taking a risk, and if the product gets into trouble because of it the
programmer should be sacked for being too expensive.

To
illustrate that point, compare what the JScript documentation says about
0.007.toFixed(2) and what IE does.

<FAQENTRY> ISTM that Section 5.1 paragraph 4 needs
correction : for 0.07 read 0.007. </FAQENTRY>


Firefox 3.0.11 & 3.0.12 give three alerts, 2 1 1.

Firefox is obviously treating the function body as a statement. To be
consistent it shouldn't implement local variables inside functions as
they aren't allowed inside statements. Perhaps they are in Firefox ?

Other browsers don't
like the syntax.

Three cheers for other browsers!

But there's a syntax error that IE8 doesn't spot. I'll not publish it in
case some idiot starts using it.

John
 
G

Garrett Smith

Dr said:
In comp.lang.javascript message <[email protected]
8924D9443D28E23ED5CD>, Sat, 25 Jul 2009 17:34:11, John G Harris


Browser documentation tells at best what the documenter thought the
browser would or should do. It is no substitute for actual test. To
illustrate that point, compare what the JScript documentation says about
0.007.toFixed(2) and what IE does.

I searched around for the JScript documentation you mentioned and found:
http://msdn.microsoft.com/en-us/library/sstyff0z(VS.85).aspx

| The toFixed method returns a string representation of a number in
| fixed-point notation. The string contains one digit before the
| significand's decimal point, and must contain fractionDigits digits
| after it.

Is that the documentation you were referring to?

Testing that number 0.007 in IE:

javascript:alert( 0.007.toFixed(2) )

Returns a string representation that contains one digit before the
significand's decimal point ("0"), a decimal point, and fractionDigits
after it ("00").

The result in IE is "0.00".

According to JScript documentation, I am not sure how to prove that that
is technically incorrect.
<FAQENTRY> ISTM that Section 5.1 paragraph 4 needs
correction : for 0.07 read 0.007. </FAQENTRY>

Why? IE 7 has incorrect result with 0.07.

You said so yourself:
http://www.merlyn.demon.co.uk/js-rndg1.htm#toF

Garrett
 
T

-TNO-

Luckily it's not currently scheduled to go in ES5.


Why luckily? Not having to type the extra boilerplate would be
beneficial I would think in a few situations. For example:

function Y(X)
(function(procedure)
X(function(arg) procedure(procedure)(arg)))
(function(procedure)
X(function(arg) procedure(procedure)(arg)))
 
G

Gabriel Gilini

On 24 jul, 07:39, Richard Cornford <[email protected]>
wrote:
[snip]
| The source text of an ECMAScript program is first converted into
| a sequence of input elements, which are either tokens, line
| terminators, comments, or white space. The source text is scanned
| from left to right, repeatedly taking the longest possible
| sequence of characters as the next input element.

It is the requirement to take "the longest possible sequence of
characters" that means that:-

returnX

- will always be a single Identifier token and never a ReservedWord
token followed by an Identifier token (as defined in section 7.5).

Well, that explains it.
Thanks to everyone that took the time to answer, I really should have
looked closer at that.
 
D

Dr J R Stockton

In comp.lang.javascript message <[email protected]
8924D9443D28E23ED5CD>, Mon, 27 Jul 2009 16:21:32, John G Harris
A programmer who relies on any particular non-standard behaviour is
taking a risk, and if the product gets into trouble because of it the
programmer should be sacked for being too expensive.

Certainly. But one should also not rely on standard behaviour unless
that has been confirmed by test. However, if the browser documentation
indicates non-standard behaviour and the browser itself conforms, like
other browsers, with the standard, then it should be safe enough to
assume that the documentation is wrong; though the really cautious would
avoid using that construct.

Firefox is obviously treating the function body as a statement. To be
consistent it shouldn't implement local variables inside functions as
they aren't allowed inside statements. Perhaps they are in Firefox ?

ISTM otherwise. It is treating the "function A()" as needing a
following compound statement, and allowing a simple statement "alert(1)"
where a compound one is expected. The combination is wrong.
Three cheers for other browsers!

But there's a syntax error that IE8 doesn't spot. I'll not publish it in
case some idiot starts using it.

Would it not be better to publish it? Firstly, you could be wrong; and
secondly, publication might prevent others using it. There is a
hypothetical thirdly : that publication might lead to MS correcting it.
That has not worked with 0.7.toFixed(), and not with VBScript DatePart
ISO WeekNumber either.
 
D

Dr J R Stockton

In comp.lang.javascript message <[email protected]
september.org>, Mon, 27 Jul 2009 09:57:29, Garrett Smith
Dr J R Stockton wrote:

I searched around for the JScript documentation you mentioned and found:
http://msdn.microsoft.com/en-us/library/sstyff0z(VS.85).aspx

| The toFixed method returns a string representation of a number in
| fixed-point notation. The string contains one digit before the
| significand's decimal point, and must contain fractionDigits digits
| after it.

Is that the documentation you were referring to?

They have so much - it might be - it is equivalent. The URL that I had
is no longer good.
Testing that number 0.007 in IE:

javascript:alert( 0.007.toFixed(2) )

Returns a string representation that contains one digit before the
significand's decimal point ("0"), a decimal point, and fractionDigits
after it ("00").

The result in IE is "0.00".

According to JScript documentation, I am not sure how to prove that
that is technically incorrect.

Elementary arithmetic knowledge; what other browsers do; 16262 15.7.4.5
step 10. The documentation is not good; it is compatible with always
returning zero, to the required number of places; the error with that
will never exceed 100%.

Why? IE 7 has incorrect result with 0.07.

The FAQ section Subject includes "as a String with exactly 2 decimal
places?". IE gets 0.07 to 2 places correct. Therefore, an unqualified
0.07 is not a good example; 0.07 only errs with toFixed(1).

Consider : the expression (0.007).toFixed(2) gives 0.00 in JScript.

QUERY : is it now reasonably safe to call toFixed unconditionally, it is
an existence test needed still?
 
J

John G Harris

Why luckily? Not having to type the extra boilerplate would be
beneficial I would think in a few situations. For example:

function Y(X)
(function(procedure)
X(function(arg) procedure(procedure)(arg)))
(function(procedure)
X(function(arg) procedure(procedure)(arg)))

It's not very readable, is it ?

Crockford enthusiasts will notice that leaving out the curly brackets in
this way is a bad part of JavaScript and hence will not be permitted by
JSLint.

John
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
474,093
Messages
2,570,607
Members
47,226
Latest member
uatas12

Latest Threads

Top