Last active
February 10, 2016 20:27
-
-
Save ericelliott/08f8a1834d83b0c7a8ed to your computer and use it in GitHub Desktop.
What's in a name?
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
UPDATE: This bug has been fixed, but be warned: | |
concise methods and unnamed function expression assignments | |
in object literals DO NOT make the function name | |
available to reference inside the function body. | |
If you want method recursion, always use a named | |
function expression. | |
*/ | |
/* | |
Babel supports tail call optimization for functions that | |
have a function call in tail position. | |
*/ | |
// This... | |
let foo = function foo (count, limit) { | |
c = count + 1; | |
console.log(c); | |
if (c >= limit) { | |
return c; | |
} | |
return foo(c, limit); | |
} | |
// Gets compiled to: | |
"use strict"; | |
var foo = function foo(_x, _x2) { | |
var _again = true; | |
_function: while (_again) { | |
_again = false; | |
var count = _x, | |
limit = _x2; | |
c = count + 1; | |
console.log(c); | |
if (c >= limit) { | |
return c; | |
} | |
_x = c; | |
_x2 = limit; | |
_again = true; | |
continue _function; | |
} | |
}; | |
/* | |
Note that instead of calling the function and allocating a new | |
stack frame, babel is able to optimize this into a while loop... | |
But watch what happens if we omit the name in the function | |
expression... | |
*/ | |
let foo = function (count, limit) { | |
// This first line is all we changed... | |
// Compiles to | |
"use strict"; | |
var foo = (function (_foo) { | |
function foo(_x, _x2) { | |
return _foo.apply(this, arguments); | |
} | |
foo.toString = function () { | |
return _foo.toString(); | |
}; | |
return foo; | |
})(function (count, limit) { | |
c = count + 1; | |
console.log(c); | |
if (c >= limit) { | |
return c; | |
} | |
return foo(c, limit); | |
}); | |
/* | |
Why is this happening? Because the ES6 spec | |
specifies that JS engines should infer function | |
names when they're not provided so they can | |
provide better stack traces than a big | |
block of (Anonymous) function calls. | |
In the example, Babel is jumping through hoops to | |
make the function name behave as expected in the | |
debugger... at the expense of the tail call | |
optimization! | |
The result is, for the sake of a minor | |
convenience in the debugger, Babel risks blowing | |
up the stack frame and breaking your program. | |
Oops! So, remember to always name | |
your function expressions, even with ES6 | |
(if you're compiling to ES5). | |
I filed this as a bug here: | |
https://github.com/babel/babel/issues/1367 | |
*/ |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Now there's a custom ESLint rule for this issue. Use it! =)