Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

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

5 views
Skip to first unread message

Ry Nohryb

unread,
Aug 19, 2010, 1:04:51 PM8/19/10
to
try {} catch (e) {} finally { return }
--> SyntaxError: Invalid return statement.

How come ?
--
Jorge.

Ry Nohryb

unread,
Aug 19, 2010, 1:07:35 PM8/19/10
to

Arrghhh:

(function () {


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

})()
--> undefined

Sorry.
--
Jorge.

Michael Haufe ("TNO")

unread,
Aug 19, 2010, 1:49:41 PM8/19/10
to

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"

Lasse Reichstein Nielsen

unread,
Aug 19, 2010, 3:16:08 PM8/19/10
to
Ry Nohryb <jo...@jorgechamorro.com> writes:

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

/L
--
Lasse Reichstein Holst Nielsen
'Javascript frameworks is a disruptive technology'

Ry Nohryb

unread,
Aug 19, 2010, 5:45:23 PM8/19/10
to
On Aug 19, 7:49 pm, "Michael Haufe (\"TNO\")"

<t...@thenewobjective.com> wrote:
>
> 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" ?
--
Jorge.

Michael Haufe ("TNO")

unread,
Aug 19, 2010, 9:06:16 PM8/19/10
to

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"

Garrett Smith

unread,
Aug 19, 2010, 10:14:39 PM8/19/10
to
On 2010-08-19 02:45 PM, Ry Nohryb wrote:
> On Aug 19, 7:49 pm, "Michael Haufe (\"TNO\")"
> <t...@thenewobjective.com> wrote:
>>
>> 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.

>> 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" ?

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.
--
Garrett

Michael Haufe ("TNO")

unread,
Aug 19, 2010, 10:57:50 PM8/19/10
to
On Aug 19, 9:14 pm, Garrett Smith <dhtmlkitc...@gmail.com> wrote:
> On 2010-08-19 02:45 PM, Ry Nohryb wrote:
>
> > On Aug 19, 7:49 pm, "Michael Haufe (\"TNO\")"
> > <t...@thenewobjective.com>  wrote:
>
> >> 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.

Yes, that is why I was careful in my use of quotation marks.

Dmitry A. Soshnikov

unread,
Aug 20, 2010, 3:42:41 AM8/20/10
to
On 20.08.2010 5:06, Michael Haufe ("TNO") wrote:
> On Aug 19, 4:45 pm, Ry Nohryb<jo...@jorgechamorro.com> wrote:
>> On Aug 19, 7:49 pm, "Michael Haufe (\"TNO\")"
>>
>> <t...@thenewobjective.com> wrote:
>>
>>> 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" ?
>

<snip>

> 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.

Lasse Reichstein Nielsen

unread,
Aug 22, 2010, 6:38:27 AM8/22/10
to
Garrett Smith <dhtmlk...@gmail.com> writes:

> On 2010-08-19 02:45 PM, Ry Nohryb wrote:
>> On Aug 19, 7:49 pm, "Michael Haufe (\"TNO\")"
>> <t...@thenewobjective.com> wrote:
>>> 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" ?
>
> 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.

Garrett Smith

unread,
Aug 22, 2010, 2:39:04 PM8/22/10
to
On 2010-08-22 03:38 AM, Lasse Reichstein Nielsen wrote:
> Garrett Smith<dhtmlk...@gmail.com> writes:
>
>> On 2010-08-19 02:45 PM, Ry Nohryb wrote:
>>> On Aug 19, 7:49 pm, "Michael Haufe (\"TNO\")"
>>> <t...@thenewobjective.com> wrote:
>>>> 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" ?
>>
>> 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.

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.

[...]

>
>> 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.
>

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.
--
Garrett

0 new messages