Stage -1 Draft / October 18, 2015

Headless Arrow Functions

Introduction#

ES2015 arrow functions require an empty parameter list when you don't want any parameters, eg: p.then(() => resolve()). This proposal makes it syntactically valid to omit the empty parameter list, eg: p.then(=> resolve()). The [no LineTerminator here] restriction after the ArrowParameters of ArrowFunction ensures there is no syntactic difficulty. Minor modifications are required to the grammar and a few abstract operations.

Interaction with Async Functions#

In the current async functions proposal, there is a syntactic form for async arrow functions:


      async () => 1;
    

This might lead developers to try to use the following headless async arrow:


      async => new Promise();
    

Unfortunately, this is a perfectly valid arrow function with one parameter named async. This may make this proposal untenable, or it might be a good reason to modify or remove async arrows from the async functions proposal.

1Arrow Function Definitions#

The alernative ArrowFunction:=>ConciseBody is added to ArrowFunction:

ArrowFunction[In, Yield, Await]:ArrowParameters[?Yield, ?Await][no LineTerminator here]=>ConciseBody[?In] =>ConciseBody[?In]

1.1Runtime Semantics: Evaluation#

ArrowFunction:=>ConciseBody
  1. If the function code for this ArrowFunction is strict mode code, let strict be true. Otherwise let strict be false.
  2. Let scope be the LexicalEnvironment of the running execution context.
  3. Let closure be FunctionCreate(Arrow, empty, ConciseBody, scope, strict).
  4. Return closure.

1.2Static Semantics: Early Errors#

ArrowFunction:=>ConciseBody

1.3Static Semantics: HasName#

ArrowFunction:=>ConciseBody
  1. Return false.

1.4Static Semantics: Contains#

With parameter symbol.

ArrowFunction:=>ConciseBody
  1. If symbol is not one of NewTarget, SuperProperty, SuperCall, super or this, return false.
  2. Return ConciseBody Contains symbol.

2Table 27#

Table 27's row for [[FormalParameters]] is modified as follows:

Table 1: Modified Table 27
Internal SlotTypeDescription
[[FormalParameters]]Parse Node | emptyIf the value is a Parse Node, then it is the root parse node of the source text that defines the function's formal parameter list.

3FunctionDeclarationInstantiation(func, argumentsList)#

Note

FunctionDeclarationInstantiation is performed as follows using arguments func and argumentsList. func is the function object for which the execution context is being established.

  1. Let calleeContext be the running execution context.
  2. Let env be the LexicalEnvironment of calleeContext.
  3. Let envRec be env's EnvironmentRecord.
  4. Let code be the value of the [[ECMAScriptCode]] internal slot of func.
  5. Let strict be the value of the [[Strict]] internal slot of func.
  6. Let formals be the value of the [[FormalParameters]] internal slot of func.
  7. If formals is empty, then
    1. Let hasDuplicates be false.
    2. Let parameterNames be a new empty List.
    3. Let simpleParameterList be true.
    4. Let hasParameterExpressions be false.
  8. Else,
    1. Let parameterNames be the BoundNames of formals.
    2. If parameterNames has any duplicate entries, let hasDuplicates be true. Otherwise, let hasDuplicates be false.
    3. Let simpleParameterList be IsSimpleParameterList of formals.
    4. Let hasParameterExpressions be ContainsExpression of formals.
  9. Let varNames be the VarDeclaredNames of code.
  10. Let varDeclarations be the VarScopedDeclarations of code.
  11. Let lexicalNames be the LexicallyDeclaredNames of code.
  12. Let functionNames be an empty List.
  13. Let functionsToInitialize be an empty List.
  14. For each d in varDeclarations, in reverse list order do
    1. If d is neither a VariableDeclaration or a ForBinding, then
      1. Assert: d is either a FunctionDeclaration or a GeneratorDeclaration.
      2. Let fn be the sole element of the BoundNames of d.
      3. If fn is not an element of functionNames, then
        1. Insert fn as the first element of functionNames.
        2. NOTE If there are multiple |FunctionDeclaration|s or |GeneratorDeclaration|s for the same name, the last declaration is used.
        3. Insert d as the first element of functionsToInitialize.
  15. Let argumentsObjectNeeded be true.
  16. If the value of the [[ThisMode]] internal slot of func is lexical, then
    1. NOTE Arrow functions never have an arguments objects.
    2. Let argumentsObjectNeeded be false.
  17. Else if "arguments" is an element of parameterNames, then
    1. Let argumentsObjectNeeded be false.
  18. Else if hasParameterExpressions is false, then
    1. If "arguments" is an element of functionNames or if "arguments" is an element of lexicalNames, then
      1. Let argumentsObjectNeeded be false.
  19. For each String paramName in parameterNames, do
    1. Let alreadyDeclared be envRec.HasBinding(paramName).
    2. NOTE Early errors ensure that duplicate parameter names can only occur in non-strict functions that do not have parameter default values or rest parameters.
    3. If alreadyDeclared is false, then
      1. Let status be envRec.CreateMutableBinding(paramName).
      2. If hasDuplicates is true, then
        1. Let status be envRec.InitializeBinding(paramName, undefined).
      3. Assert: status is never an abrupt completion for either of the above operations.
  20. If argumentsObjectNeeded is true, then
    1. If strict is true or if simpleParameterList is false, then
      1. Let ao be CreateUnmappedArgumentsObject(argumentsList).
    2. Else,
      1. NOTE mapped argument object is only provided for non-strict functions that don't have a rest parameter, any parameter default value initializers, or any destructured parameters .
      2. Let ao be CreateMappedArgumentsObject(func, formals, argumentsList, env).
    3. ReturnIfAbrupt(ao).
    4. If strict is true, then
      1. Let status be envRec.CreateImmutableBinding("arguments").
    5. Else,
      1. Let status be envRec.CreateMutableBinding("arguments").
    6. Assert: status is never an abrupt completion.
    7. Call envRec.InitializeBinding("arguments", ao).
    8. Append "arguments" to parameterNames.
  21. Let iteratorRecord be Record {[[iterator]]: CreateListIterator(argumentsList), [[done]]: false}.
  22. If formals is not empty, then
    1. If hasDuplicates is true, then
      1. Let formalStatus be IteratorBindingInitialization for formals with iteratorRecord and undefined as arguments.
    2. Else,
      1. Let formalStatus be IteratorBindingInitialization for formals with iteratorRecord and env as arguments.
    3. ReturnIfAbrupt(formalStatus).
  23. If hasParameterExpressions is false, then
    1. NOTE Only a single lexical environment is needed for the parameters and top-level vars.
    2. Let instantiatedVarNames be a copy of the List parameterNames.
    3. For each n in varNames, do
      1. If n is not an element of instantiatedVarNames, then
        1. Append n to instantiatedVarNames.
        2. Let status be envRec.CreateMutableBinding(n).
        3. Assert: status is never an abrupt completion.
        4. Call envRec.InitializeBinding(n, undefined).
    4. Let varEnv be env.
    5. Let varEnvRec be envRec.
  24. Else,
    1. NOTE A separate Environment Record is needed to ensure that closures created by expressions in the formal parameter list do not have visibility of declarations in the function body.
    2. Let varEnv be NewDeclarativeEnvironment(env).
    3. Let varEnvRec be varEnv's EnvironmentRecord.
    4. Set the VariableEnvironment of calleeContext to varEnv.
    5. Let instantiatedVarNames be a new empty List.
    6. For each n in varNames, do
      1. If n is not an element of instantiatedVarNames, then
        1. Append n to instantiatedVarNames.
        2. Let status be varEnvRec.CreateMutableBinding(n).
        3. Assert: status is never an abrupt completion.
        4. If n is not an element of parameterNames or if n is an element of functionNames, let initialValue be undefined.
        5. else,
          1. Let initialValue be envRec.GetBindingValue(n, false).
          2. ReturnIfAbrupt(initialValue).
        6. Call varEnvRec.InitializeBinding(n, initialValue).
        7. NOTE vars whose names are the same as a formal parameter, initially have the same value as the corresponding initialized parameter.
  25. NOTE: Annex adds additional steps at this point.
  26. If strict is false, then
    1. Let lexEnv be NewDeclarativeEnvironment(varEnv).
    2. NOTE: Non-strict functions use a separate lexical Environment Record for top-level lexical declarations so that a direct eval (see 12.3.4.1) can determine whether any var scoped declarations introduced by the eval code conflict with pre-existing top-level lexically scoped declarations. This is not needed for strict functions because a strict direct eval always places all declarations into a new Environment Record.
  27. Else, let lexEnv be varEnv.
  28. Let lexEnvRec be lexEnv's EnvironmentRecord.
  29. Set the LexicalEnvironment of calleeContext to lexEnv.
  30. Let lexDeclarations be the LexicallyScopedDeclarations of code.
  31. For each element d in lexDeclarations do
    1. NOTE A lexically declared name cannot be the same as a function/generator declaration, formal parameter, or a var name. Lexically declared names are only instantiated here but not initialized.
    2. For each element dn of the BoundNames of d do
      1. If IsConstantDeclaration of d is true, then
        1. Let status be lexEnvRec.CreateImmutableBinding(dn, true).
      2. Else,
        1. Let status be lexEnvRec.CreateMutableBinding(dn, false).
    3. Assert: status is never an abrupt completion.
  32. For each parsed grammar phrase f in functionsToInitialize, do
    1. Let fn be the sole element of the BoundNames of f.
    2. Let fo be the result of performing InstantiateFunctionObject for f with argument lexEnv.
    3. Let status be varEnvRec.SetMutableBinding(fn, fo, false).
    4. Assert: status is never an abrupt completion.
  33. Return NormalCompletion(empty).

ACopyright & Software License#

Copyright Notice

© 2015 Brian Terlson

Software License

All Software contained in this document ("Software") is protected by copyright and is being made available under the "BSD License", included below. This Software may be subject to third party rights (rights from parties other than Ecma International), including patent rights, and no licenses under such third party rights are granted under this license even if the third party concerned is a member of Ecma International. SEE THE ECMA CODE OF CONDUCT IN PATENT MATTERS AVAILABLE AT http://www.ecma-international.org/memento/codeofconduct.htm FOR INFORMATION REGARDING THE LICENSING OF PATENT CLAIMS THAT ARE REQUIRED TO IMPLEMENT ECMA INTERNATIONAL STANDARDS.

Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:

  1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
  2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
  3. Neither the name of the authors nor Ecma International may be used to endorse or promote products derived from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE ECMA INTERNATIONAL "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ECMA INTERNATIONAL BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.