Skip to content

Instantly share code, notes, and snippets.

@littledan
Last active November 13, 2015 01:49
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save littledan/09f08c9bf473a800f5b3 to your computer and use it in GitHub Desktop.
Save littledan/09f08c9bf473a800f5b3 to your computer and use it in GitHub Desktop.

In this proposed alternative to sloppy-mode function hoisting semantics, sloppy-mode FunctionDeclaration are always single var-style bindings. The var is set to the value of the function at the top of the block where the FunctionDeclaration occurs. I believe these semantics roughly match IE10 and earlier sloppy mode function hoisting semantics.

Goals

  • Maintain compatibility at the intersection of what browsers have supported for a long time
  • Support is self-defining functions defined in blocks (tc39/ecma262#162)
  • If possible, be intelligible for users and implementors (simple semantics win out when they make sense)
  • Preserve strict-mode lexical scoping of FunctionDeclarations (this proposal only affects sloppy mode)

Non-goals

  • Make a lexical binding in sloppy mode, and generally try to make sloppy mode block-scoped FunctionDeclarations act like lexical bindings, including suppressing errors, when possible

Desugaring example

To give an example in terms of imprecise desugaring, the following declaration would turn into the next code:

(function() {
  A
  if (foo) {
    B
    function bar() { }
    C
  }
  D
})();

would have semantics that are something like this:

(function() {
  var bar;
  A
  if (foo) {
    bar = function() {}
    B
    C
  }
  D
})();

so B, C and D would experience the new binding. In this sense, the proposal is just like Annex B 3.3. However, the difference is that only a single binding is created, rather than two in Annex B 3.3, a lexical and var-style binding.

Precise semantics

Implementing this change in the ECMAScript specification will be rather cross-cutting. For this reason, I think it would be impractical to do within Annex B, and it would be better to think of it together with the rest of strict/sloppy semantics. (I'd suggest that we reconsider the split of Annex B from the rest of the spec--Annex B together with earlier parts of the ES spec are inseparably both supported by all usable ECMAScript implementations.)

Parts of the spec that would need to be changed:

  • BlockDeclarationInstantiation step 2.b. starts with a strict/sloppy mode check. In strict mode (or with generators, which maintain a single lexical binding), it maintains its current behavior; in sloppy mode, it sets the variable binding for a FunctionDeclaration contained in its block to the value defined in the block.
  • FunctionDeclarations in sloppy mode should be in VarScopedDeclarations rather than LexicallyScopedDeclarations even if they are in a block, and similarly, should be in LexicallyDeclaredNames rather than VarDeclaredNames.
  • FunctionDeclarationInstantiation, GlobalDeclarationInstantiation and EvalDeclarationInstantiation need to treat sloppy-mode block-scoped function declarations differently from top-level (within that scope) declarations. Namely, rather than choosing the last one and initializing the binding to that, they should initialize the binding to undefined. These algorithms can do the test similarly to how Annex B 3.3 does: "For each FunctionDeclaration f that is directly contained in the StatementList of a Block, CaseClause, or DefaultClause,"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment