try {} catch (e) {} finally { return }

R

Ry Nohryb

try {} catch (e) {} finally { return }
--> SyntaxError: Invalid return statement.

How come ?
 
R

Ry Nohryb

try {} catch (e) {} finally { return }
--> SyntaxError: Invalid return statement.

How come ?

Arrghhh:

(function () {
try {} catch (e) {} finally { return }
})()
--> undefined

Sorry.
 
M

Michael Haufe (\TNO\)

Arrghhh:

(function () {
  try {} catch (e) {} finally { return }})()

--> undefined

Sorry.

The finally block "always" executes. Here's something a little more
interesting:

var a = (function () {
try { return "foo" } catch (e) {} finally { return "bar" }
})();

a // "bar"
 
L

Lasse Reichstein Nielsen

Ry Nohryb said:
try {} catch (e) {} finally { return }
--> SyntaxError: Invalid return statement.

How come ?

return;
--> SyntaxError: Invalid return statement.

ES5, section 12.9:
"An ECMAScript program is considered syntactically incorrect if it
contains a return statement that is not within a FunctionBody."

/L
 
R

Ry Nohryb

The finally block "always" executes. Here's something a little more
interesting:

var a = (function () {
  try { return "foo" } catch (e) {} finally { return "bar" }

})();

a // "bar"

Yep. Thanks. Very interesting indeed! What has happened to the first
return "foo" ?
 
M

Michael Haufe (\TNO\)

Yep. Thanks. Very interesting indeed! What has happened to the first
return "foo" ?

I could quote the specification, but I doubt that would have much
meaning. What I believe the reasoning to be is that because a function
can only return once, the return statement of the finally block takes
precedence since it is "guaranteed" to always execute. Anything that
happens inside the try or catch block before a return statement will
still occur though:

var a = (function () {
try { WScript.Echo("msg"); return "foo" } catch (e) {} finally
{ return "bar" }
})();

//"msg" is displayed and a == "bar"
 
G

Garrett Smith

The finally block "always" executes.[...]

Per spec, yes. Now test that premise in any version of internet explorer
and you'll find it doesn't quite work.

javascript: try { x } finally { alert(12); }

In IE7 and below, a ReferenceError is thrown (`x` is undefined) and the
finally block is *not* executed. In IE8 and even IE9 pr4, you'll find
that the finally block executes and then a ReferenceError is thrown.
Yep. Thanks. Very interesting indeed! What has happened to the first
return "foo" ?

Keep in mind that SyntaxError can occur at runtime and that is just what
happens in V8 and SFX.

An implementation may treat any instance of the following kinds of
runtime errors as a syntax error and therefore report it early:

* Improper uses of return, break, and continue.
* Using the eval property other than via a direct call.
* Errors in regular expression literals.
* Attempts to call PutValue on a value that is not a reference (for
example, executing the assignment statement 3= 4).

Regarding your example, if the implementation throws a SyntaxError
early, then this should be found from the first return statement in the
try block (because a program is scanned from left to right) and so the
program ends there.

Otherwise, the execution will enter the `try` block and when evaluating
the ReturnStatement a SyntaxError must be thrown. When that happens, the
catch block is evaluated with the parameter of the SyntaxError. The
catch block completes and the finally block is evaluated and that has a
return statement which results in a SyntaxError being thrown.

Thush, your example has two possible valid execution paths. What happens
in V8 (Chromium's js engine) and SFX (Webkit's engine), is that the code
enters the try block, an runtime SyntaxError is thrown, the code enters
the catch block, the code enters the finally block, where another
SyntaxError is thrown.

Versions of Spidermonkey all versions of JScript as well as Besen throw
a SyntaxError early.

Older versions of Webkit interpret the return statement by exiting
global execution context, thus, anything after the finally won't be
evaluated. That is an ECMAScript conformance violation.

javascript:var e;try{return 1;}catch(ex){e=ex;}finally{alert("err:"+e);}

Gecko, IE: throws SyntaxError msg: "return not in function"
Safari 3 and 4 alerts "err:SyntaxError:Invalid return statement."
Safari 2.x and below: alerts "err:undefined".

javascript:try{alert(1);return
1;}catch(e){alert(2)}finally{alert(3)}alert(4);

Safari 2.x and below: alert "1" then alerts "3" and nothing else.
 
D

Dmitry A. Soshnikov

What I believe the reasoning to be is that because a function
can only return once,

Yes, this is alternative paradigm to "multi-returns". But this paradigm,
a "single-return" (and which was mentioned in some design-patterns as a
good practice) is old paradigm, which was/is based on languages which
syntactically have/had only one return.

Personally, I prefer "multi-returns", because they are cleaner, e.g.
there is no sense to analyze the code, if the first check fails:

if (!foo) return;

// other stuff

return result;

Instead of "one-return":

if (!foo) result = undefined;
else if (...) result = otherThing;
else { other stuff; result = somethingElse}

return result;
the return statement of the finally block takes
precedence since it is "guaranteed" to always execute.

I think it's just a side-effect and consequence of that `finally' is
guaranteed to be executed anyway (again, to close system open handlers
e.g. in C, etc).

Dmitry.
 
L

Lasse Reichstein Nielsen

Garrett Smith said:
Keep in mind that SyntaxError can occur at runtime and that is just
what happens in V8 and SFX.

No. The return is syntactically correct and is properly executed.
Before control leaves the try/finally statement, the finally block
is then executed, remembering the the try block wanted to return
"foo". If the finally block terminates normally (doesn't throw/
return/break/continue), then the previous result is returned.
In this case, the finally block doesn't terminate normally, so
its result replaces the result of the try block.
See ES5 section 12.14.
Older versions of Webkit interpret the return statement by exiting
global execution context, thus, anything after the finally won't be
evaluated. That is an ECMAScript conformance violation.

javascript:var e;try{return 1;}catch(ex){e=ex;}finally{alert("err:"+e);}

This is a syntax error because the return is not inside a function body.
The original example was inside a function, and the return in the try
block is not a syntax error in any browser.

/L
 
G

Garrett Smith

No. The return is syntactically correct and is properly executed.

In the function example, yes, it is.

My explanation was about what I had (mis)remembered that to be was:

| try { return "foo" } catch (e) {} finally { return "bar" }
|

The explanation I provided applies to that.

[...]
This is a syntax error because the return is not inside a function body.
The original example was inside a function, and the return in the try
block is not a syntax error in any browser.

Right. In the example that was inside a function, the return statements
are syntactically valid. Thank you for clarifying that.

Regarding a return statement that appears in a block that is not inside
a function body. Again:

var e;try{return 1;}catch(ex){e=ex;}finally{alert("err:"+e);}

That example has two valid interpretations in the browsers tested and
one invalid interpretation (older Webkit).

An error must be thrown. If it is thrown early, it can't be caught and
the program terminates abruptly. Otherwise, the catch block is entered,
assigns `e=ex;` and then the finally block executes, does the alert, and
the program completes normally.
 

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

Forum statistics

Threads
474,077
Messages
2,570,566
Members
47,202
Latest member
misc.

Latest Threads

Top