On the awesomeness of fn.displayName

This post is mostly actionable for library and framework authors, but everybody should demand that their favorite library or framework[1] adopts this practice:

No function in a framework stack trace should have a useless name.

With the most useless name of them all being: (anonymous function).

Luckily over 5 years ago the Cappucino framework team had a problem: Their stack traces were bad beyond usability. The problem was that they generated lots of functions and thus there was no good way to infer a name automatically. On the other hand they knew perfectly well what the function name should be, so they persuaded the WebKit team to add the most obvious and best feature ever:

fn.displayName = “some string”

…and boom: suddenly whenever a debugger wanted to print out the name of “fn” it would say “some string” instead of “anonymous function”.

Meanwhile I was working on Joose and had a very similar problem, so I started advocating (You could Google for unproductive issue tracker threads but don’t) adding this feature to my then favorite debugger firebug and later Chrome DevTools – but no dice (Firebug did add support after it stopped being very relevant). Unfortunately some people had written papers about being super good at inferring function names (and failed to consider the limits of computability) and it was decided that hyper complicated inference should be implemented before the simple solution. Move forward 5 years, finally support (although still somewhat limited) landed in Chrome DevTools and we can start using it. Woot!

Now the original use case of displayName was to give names to functions that would otherwise have none, but this week after going on a mission to have no function in my framework that I’m building at Google be unnamed it occurred to me that there is even more potential beyond just simple naming:

Encode the most important piece of context on the stack.

Take e.g. this example:

With the awesome async stack trace support in Chrome DevTools we ge:t

Not awesome. But it is easy to make it much better:

Notice that I assigned a string that contains the actual module we requested to the displayName of the loaded callback. With this the stack trace looks like this:

There is still an anonymous function on the top because I was lazy in my example, but there is now a clear path how to get rid of all of these.

With the change in the example, when ever there is a problem in module “foo/bar” the stack will clearly state that we are in this context.

In the framework I’m working on I’m actually sometimes adding stack frames just to leave a bit more information on the stack. That brings us to an important point: Adding this information costs bytes on the wire and execution time at runtime – but every build system should have a way to get rid of these assignments in optimized/minified builds just like asserts and other debug-only code, so I consider it a non problem.

Why am I saying that is is more relevant to authors of framework/library code over regular application code? Assignment of the displayName does make the code less idiomatic (until you implement Function.prototype.withDisplayName that returns this :), so I would only recommend the reduction in maintainability if the benefits are sufficient – and with highly reused code this is almost always the case.

In the far future when we leave the stone age of debugging we’ll have fancy stuff like loggers that automatically associated log statements with stack frames, but until then go and abuse fn.displayName to make stack traces more semantic!

[1] For the purpose of this post I use library, module and framework interchangeably. Whenever you see any of those, substitute it with the word of the 3 that you have most empathy for.

AMP TSC. JavaScript infrastructure at Google. Curator of @JSConfEU. Writer at industrialempathy.com. he/him

AMP TSC. JavaScript infrastructure at Google. Curator of @JSConfEU. Writer at industrialempathy.com. he/him