How come ?
--
Jorge.
Arrghhh:
(function () {
try {} catch (e) {} finally { return }
})()
--> undefined
Sorry.
--
Jorge.
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"
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'
Yep. Thanks. Very interesting indeed! What has happened to the first
return "foo" ?
--
Jorge.
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"
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
Yes, that is why I was careful in my use of quotation marks.
<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.
> 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.
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