function variablesInFunction(tree) {
  let builder = new ScopeChainBuilder(null);
  builder.visitAny(tree);
  let scope = builder.getScopeForTree(tree);
  return scope.getAllBindingNames();
}
Gets the identifiers bound in the context of a function,
{@code tree}, other than the function name itself. For example, if
{@code tree} is:

function f(x) { var y; f(); }

Then a set containing only {@code "x"} and {@code "y"} is returned. Note
that we treat {@code "f"} as free in the body of {@code f}, because
AlphaRenamer uses this fact to determine if the function name is shadowed
by another name in the body of the function.

<p>Only identifiers that are bound <em>throughout</em> the
specified tree are returned, for example:

function f() {
  try {
  } catch (x) {
    function g(y) { }
  }
}

Reports nothing as being bound, because {@code "x"} is only bound in the
scope of the catch block; {@code "g"} is let bound to the catch block, and
{@code "y"} is only bound in the scope of {@code g}.

{@code "arguments"} is only reported as bound if it is
explicitly bound in the function. If it is not explicitly bound,
{@code "arguments"} is implicitly bound during function
invocation.

@param {FunctionDeclaration} tree
@return {StringSet}