10.2 ECMAScript Function Objects

ECMAScript function objects encapsulate parameterized ECMAScript code closed over a lexical environment and support the dynamic evaluation of that code. An ECMAScript function object is an ordinary object and has the same internal slots and the same internal methods as other ordinary objects. The code of an ECMAScript function object may be either strict mode code (11.2.2) or non-strict code. An ECMAScript function object whose code is strict mode code is called a strict function. One whose code is not strict mode code is called a non-strict function.

In addition to [[Extensible]] and [[Prototype]], ECMAScript function objects also have the internal slots listed in Table 29.

Table 29: Internal Slots of ECMAScript Function Objects
Internal Slot Type Description
[[Environment]] Environment Record The Environment Record that the function was closed over. Used as the outer environment when evaluating the code of the function.
[[FormalParameters]] Parse Node The root parse node of the source text that defines the function's formal parameter list.
[[ECMAScriptCode]] Parse Node The root parse node of the source text that defines the function's body.
[[ConstructorKind]] base | derived Whether or not the function is a derived class constructor.
[[Realm]] Realm Record The realm in which the function was created and which provides any intrinsic objects that are accessed when evaluating the function.
[[ScriptOrModule]] Script Record or Module Record The script or module in which the function was created.
[[ThisMode]] lexical | strict | global Defines how this references are interpreted within the formal parameters and code body of the function. lexical means that this refers to the this value of a lexically enclosing function. strict means that the this value is used exactly as provided by an invocation of the function. global means that a this value of undefined or null is interpreted as a reference to the global object, and any other this value is first passed to ToObject.
[[Strict]] Boolean true if this is a strict function, false if this is a non-strict function.
[[HomeObject]] Object If the function uses super, this is the object whose [[GetPrototypeOf]] provides the object where super property lookups begin.
[[SourceText]] sequence of Unicode code points The source text that defines the function.
[[IsClassConstructor]] Boolean Indicates whether the function is a class constructor. (If true, invoking the function's [[Call]] will immediately throw a TypeError exception.)

All ECMAScript function objects have the [[Call]] internal method defined here. ECMAScript functions that are also constructors in addition have the [[Construct]] internal method.

10.2.1 [[Call]] ( thisArgument, argumentsList )

The [[Call]] internal method of an ECMAScript function object F takes arguments thisArgument (an ECMAScript language value) and argumentsList (a List of ECMAScript language values). It performs the following steps when called:

  1. Assert: F is an ECMAScript function object.
  2. Let callerContext be the running execution context.
  3. Let calleeContext be PrepareForOrdinaryCall(F, undefined).
  4. Assert: calleeContext is now the running execution context.
  5. If F.[[IsClassConstructor]] is true, then
    1. Let error be a newly created TypeError object.
    2. NOTE: error is created in calleeContext with F's associated Realm Record.
    3. Remove calleeContext from the execution context stack and restore callerContext as the running execution context.
    4. Return ThrowCompletion(error).
  6. Perform OrdinaryCallBindThis(F, calleeContext, thisArgument).
  7. Let result be OrdinaryCallEvaluateBody(F, argumentsList).
  8. Remove calleeContext from the execution context stack and restore callerContext as the running execution context.
  9. If result.[[Type]] is return, return NormalCompletion(result.[[Value]]).
  10. ReturnIfAbrupt(result).
  11. Return NormalCompletion(undefined).
Note

When calleeContext is removed from the execution context stack in step 8 it must not be destroyed if it is suspended and retained for later resumption by an accessible generator object.

10.2.1.1 PrepareForOrdinaryCall ( F, newTarget )

The abstract operation PrepareForOrdinaryCall takes arguments F (a function object) and newTarget (an ECMAScript language value). It performs the following steps when called:

  1. Assert: Type(newTarget) is Undefined or Object.
  2. Let callerContext be the running execution context.
  3. Let calleeContext be a new ECMAScript code execution context.
  4. Set the Function of calleeContext to F.
  5. Let calleeRealm be F.[[Realm]].
  6. Set the Realm of calleeContext to calleeRealm.
  7. Set the ScriptOrModule of calleeContext to F.[[ScriptOrModule]].
  8. Let localEnv be NewFunctionEnvironment(F, newTarget).
  9. Set the LexicalEnvironment of calleeContext to localEnv.
  10. Set the VariableEnvironment of calleeContext to localEnv.
  11. If callerContext is not already suspended, suspend callerContext.
  12. Push calleeContext onto the execution context stack; calleeContext is now the running execution context.
  13. NOTE: Any exception objects produced after this point are associated with calleeRealm.
  14. Return calleeContext.

10.2.1.2 OrdinaryCallBindThis ( F, calleeContext, thisArgument )

The abstract operation OrdinaryCallBindThis takes arguments F (a function object), calleeContext (an execution context), and thisArgument (an ECMAScript language value). It performs the following steps when called:

  1. Let thisMode be F.[[ThisMode]].
  2. If thisMode is lexical, return NormalCompletion(undefined).
  3. Let calleeRealm be F.[[Realm]].
  4. Let localEnv be the LexicalEnvironment of calleeContext.
  5. If thisMode is strict, let thisValue be thisArgument.
  6. Else,
    1. If thisArgument is undefined or null, then
      1. Let globalEnv be calleeRealm.[[GlobalEnv]].
      2. Assert: globalEnv is a global Environment Record.
      3. Let thisValue be globalEnv.[[GlobalThisValue]].
    2. Else,
      1. Let thisValue be ! ToObject(thisArgument).
      2. NOTE: ToObject produces wrapper objects using calleeRealm.
  7. Assert: localEnv is a function Environment Record.
  8. Assert: The next step never returns an abrupt completion because localEnv.[[ThisBindingStatus]] is not initialized.
  9. Return localEnv.BindThisValue(thisValue).

10.2.1.3 Runtime Semantics: EvaluateBody

With parameters functionObject and argumentsList (a List).

FunctionBody : FunctionStatementList
  1. Return ? EvaluateFunctionBody of FunctionBody with arguments functionObject and argumentsList.
ConciseBody : ExpressionBody
  1. Return ? EvaluateConciseBody of ConciseBody with arguments functionObject and argumentsList.
GeneratorBody : FunctionBody
  1. Return ? EvaluateGeneratorBody of GeneratorBody with arguments functionObject and argumentsList.
AsyncGeneratorBody : FunctionBody
  1. Return ? EvaluateAsyncGeneratorBody of AsyncGeneratorBody with arguments functionObject and argumentsList.
AsyncFunctionBody : FunctionBody
  1. Return ? EvaluateAsyncFunctionBody of AsyncFunctionBody with arguments functionObject and argumentsList.
AsyncConciseBody : ExpressionBody
  1. Return ? EvaluateAsyncConciseBody of AsyncConciseBody with arguments functionObject and argumentsList.

10.2.1.4 OrdinaryCallEvaluateBody ( F, argumentsList )

The abstract operation OrdinaryCallEvaluateBody takes arguments F (a function object) and argumentsList (a List). It performs the following steps when called:

  1. Return the result of EvaluateBody of the parsed code that is F.[[ECMAScriptCode]] passing F and argumentsList as the arguments.

10.2.2 [[Construct]] ( argumentsList, newTarget )

The [[Construct]] internal method of an ECMAScript function object F takes arguments argumentsList (a List of ECMAScript language values) and newTarget (a constructor). It performs the following steps when called:

  1. Assert: F is an ECMAScript function object.
  2. Assert: Type(newTarget) is Object.
  3. Let callerContext be the running execution context.
  4. Let kind be F.[[ConstructorKind]].
  5. If kind is base, then
    1. Let thisArgument be ? OrdinaryCreateFromConstructor(newTarget, "%Object.prototype%").
  6. Let calleeContext be PrepareForOrdinaryCall(F, newTarget).
  7. Assert: calleeContext is now the running execution context.
  8. If kind is base, perform OrdinaryCallBindThis(F, calleeContext, thisArgument).
  9. Let constructorEnv be the LexicalEnvironment of calleeContext.
  10. Let result be OrdinaryCallEvaluateBody(F, argumentsList).
  11. Remove calleeContext from the execution context stack and restore callerContext as the running execution context.
  12. If result.[[Type]] is return, then
    1. If Type(result.[[Value]]) is Object, return NormalCompletion(result.[[Value]]).
    2. If kind is base, return NormalCompletion(thisArgument).
    3. If result.[[Value]] is not undefined, throw a TypeError exception.
  13. Else, ReturnIfAbrupt(result).
  14. Return ? constructorEnv.GetThisBinding().

10.2.3 OrdinaryFunctionCreate ( functionPrototype, sourceText, ParameterList, Body, thisMode, Scope )

The abstract operation OrdinaryFunctionCreate takes arguments functionPrototype (an Object), sourceText (a sequence of Unicode code points), ParameterList (a Parse Node), Body (a Parse Node), thisMode (either lexical-this or non-lexical-this), and Scope (an Environment Record). sourceText is the source text of the syntactic definition of the function to be created. It performs the following steps when called:

  1. Assert: Type(functionPrototype) is Object.
  2. Let internalSlotsList be the internal slots listed in Table 29.
  3. Let F be ! OrdinaryObjectCreate(functionPrototype, internalSlotsList).
  4. Set F.[[Call]] to the definition specified in 10.2.1.
  5. Set F.[[SourceText]] to sourceText.
  6. Set F.[[FormalParameters]] to ParameterList.
  7. Set F.[[ECMAScriptCode]] to Body.
  8. If the source text matching Body is strict mode code, let Strict be true; else let Strict be false.
  9. Set F.[[Strict]] to Strict.
  10. If thisMode is lexical-this, set F.[[ThisMode]] to lexical.
  11. Else if Strict is true, set F.[[ThisMode]] to strict.
  12. Else, set F.[[ThisMode]] to global.
  13. Set F.[[IsClassConstructor]] to false.
  14. Set F.[[Environment]] to Scope.
  15. Set F.[[ScriptOrModule]] to GetActiveScriptOrModule().
  16. Set F.[[Realm]] to the current Realm Record.
  17. Set F.[[HomeObject]] to undefined.
  18. Let len be the ExpectedArgumentCount of ParameterList.
  19. Perform ! SetFunctionLength(F, len).
  20. Return F.

10.2.4 AddRestrictedFunctionProperties ( F, realm )

The abstract operation AddRestrictedFunctionProperties takes arguments F (a function object) and realm (a Realm Record). It performs the following steps when called:

  1. Assert: realm.[[Intrinsics]].[[%ThrowTypeError%]] exists and has been initialized.
  2. Let thrower be realm.[[Intrinsics]].[[%ThrowTypeError%]].
  3. Perform ! DefinePropertyOrThrow(F, "caller", PropertyDescriptor { [[Get]]: thrower, [[Set]]: thrower, [[Enumerable]]: false, [[Configurable]]: true }).
  4. Return ! DefinePropertyOrThrow(F, "arguments", PropertyDescriptor { [[Get]]: thrower, [[Set]]: thrower, [[Enumerable]]: false, [[Configurable]]: true }).

10.2.4.1 %ThrowTypeError% ( )

The %ThrowTypeError% intrinsic is an anonymous built-in function object that is defined once for each realm. When %ThrowTypeError% is called it performs the following steps:

  1. Throw a TypeError exception.

The value of the [[Extensible]] internal slot of a %ThrowTypeError% function is false.

The "length" property of a %ThrowTypeError% function has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }.

The "name" property of a %ThrowTypeError% function has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }.

10.2.5 MakeConstructor ( F [ , writablePrototype [ , prototype ] ] )

The abstract operation MakeConstructor takes argument F (a function object) and optional arguments writablePrototype (a Boolean) and prototype (an Object). It converts F into a constructor. It performs the following steps when called:

  1. Assert: F is an ECMAScript function object or a built-in function object.
  2. If F is an ECMAScript function object, then
    1. Assert: IsConstructor(F) is false.
    2. Assert: F is an extensible object that does not have a "prototype" own property.
    3. Set F.[[Construct]] to the definition specified in 10.2.2.
  3. Set F.[[ConstructorKind]] to base.
  4. If writablePrototype is not present, set writablePrototype to true.
  5. If prototype is not present, then
    1. Set prototype to ! OrdinaryObjectCreate(%Object.prototype%).
    2. Perform ! DefinePropertyOrThrow(prototype, "constructor", PropertyDescriptor { [[Value]]: F, [[Writable]]: writablePrototype, [[Enumerable]]: false, [[Configurable]]: true }).
  6. Perform ! DefinePropertyOrThrow(F, "prototype", PropertyDescriptor { [[Value]]: prototype, [[Writable]]: writablePrototype, [[Enumerable]]: false, [[Configurable]]: false }).
  7. Return NormalCompletion(undefined).

10.2.6 MakeClassConstructor ( F )

The abstract operation MakeClassConstructor takes argument F. It performs the following steps when called:

  1. Assert: F is an ECMAScript function object.
  2. Assert: F.[[IsClassConstructor]] is false.
  3. Set F.[[IsClassConstructor]] to true.
  4. Return NormalCompletion(undefined).

10.2.7 MakeMethod ( F, homeObject )

The abstract operation MakeMethod takes arguments F and homeObject. It configures F as a method. It performs the following steps when called:

  1. Assert: F is an ECMAScript function object.
  2. Assert: Type(homeObject) is Object.
  3. Set F.[[HomeObject]] to homeObject.
  4. Return NormalCompletion(undefined).

10.2.8 SetFunctionName ( F, name [ , prefix ] )

The abstract operation SetFunctionName takes arguments F (a function object) and name (a property key) and optional argument prefix (a String). It adds a "name" property to F. It performs the following steps when called:

  1. Assert: F is an extensible object that does not have a "name" own property.
  2. Assert: Type(name) is either Symbol or String.
  3. Assert: If prefix is present, then Type(prefix) is String.
  4. If Type(name) is Symbol, then
    1. Let description be name's [[Description]] value.
    2. If description is undefined, set name to the empty String.
    3. Else, set name to the string-concatenation of "[", description, and "]".
  5. If F has an [[InitialName]] internal slot, then
    1. Set F.[[InitialName]] to name.
  6. If prefix is present, then
    1. Set name to the string-concatenation of prefix, the code unit 0x0020 (SPACE), and name.
    2. If F has an [[InitialName]] internal slot, then
      1. Optionally, set F.[[InitialName]] to name.
  7. Return ! DefinePropertyOrThrow(F, "name", PropertyDescriptor { [[Value]]: name, [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }).

10.2.9 SetFunctionLength ( F, length )

The abstract operation SetFunctionLength takes arguments F (a function object) and length (a non-negative integer or +∞). It adds a "length" property to F. It performs the following steps when called:

  1. Assert: F is an extensible object that does not have a "length" own property.
  2. Return ! DefinePropertyOrThrow(F, "length", PropertyDescriptor { [[Value]]: 𝔽(length), [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }).

10.2.10 FunctionDeclarationInstantiation ( func, argumentsList )

Note 1

When an execution context is established for evaluating an ECMAScript function a new function Environment Record is created and bindings for each formal parameter are instantiated in that Environment Record. Each declaration in the function body is also instantiated. If the function's formal parameters do not include any default value initializers then the body declarations are instantiated in the same Environment Record as the parameters. If default value parameter initializers exist, a second Environment Record is created for the body declarations. Formal parameters and functions are initialized as part of FunctionDeclarationInstantiation. All other bindings are initialized during evaluation of the function body.

The abstract operation FunctionDeclarationInstantiation takes arguments func (a function object) and argumentsList. func is the function object for which the execution context is being established. It performs the following steps when called:

  1. Let calleeContext be the running execution context.
  2. Let code be func.[[ECMAScriptCode]].
  3. Let strict be func.[[Strict]].
  4. Let formals be func.[[FormalParameters]].
  5. Let parameterNames be the BoundNames of formals.
  6. If parameterNames has any duplicate entries, let hasDuplicates be true. Otherwise, let hasDuplicates be false.
  7. Let simpleParameterList be IsSimpleParameterList of formals.
  8. 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 a new empty List.
  13. Let functionsToInitialize be a new empty List.
  14. For each element d of varDeclarations, in reverse List order, do
    1. If d is neither a VariableDeclaration nor a ForBinding nor a BindingIdentifier, then
      1. Assert: d is either a FunctionDeclaration, a GeneratorDeclaration, an AsyncFunctionDeclaration, or an AsyncGeneratorDeclaration.
      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 function declarations 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 func.[[ThisMode]] is lexical, then
    1. NOTE: Arrow functions never have an arguments objects.
    2. Set argumentsObjectNeeded to false.
  17. Else if "arguments" is an element of parameterNames, then
    1. Set argumentsObjectNeeded to 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. Set argumentsObjectNeeded to false.
  19. If strict is true or if hasParameterExpressions is false, then
    1. NOTE: Only a single Environment Record is needed for the parameters and top-level vars.
    2. Let env be the LexicalEnvironment of calleeContext.
  20. Else,
    1. NOTE: A separate Environment Record is needed to ensure that bindings created by direct eval calls in the formal parameter list are outside the environment where parameters are declared.
    2. Let calleeEnv be the LexicalEnvironment of calleeContext.
    3. Let env be NewDeclarativeEnvironment(calleeEnv).
    4. Assert: The VariableEnvironment of calleeContext is calleeEnv.
    5. Set the LexicalEnvironment of calleeContext to env.
  21. For each String paramName of parameterNames, do
    1. Let alreadyDeclared be env.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. Perform ! env.CreateMutableBinding(paramName, false).
      2. If hasDuplicates is true, then
        1. Perform ! env.InitializeBinding(paramName, undefined).
  22. 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: A 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. If strict is true, then
      1. Perform ! env.CreateImmutableBinding("arguments", false).
    4. Else,
      1. Perform ! env.CreateMutableBinding("arguments", false).
    5. Call env.InitializeBinding("arguments", ao).
    6. Let parameterBindings be a List whose elements are the elements of parameterNames, followed by "arguments".
  23. Else,
    1. Let parameterBindings be parameterNames.
  24. Let iteratorRecord be CreateListIteratorRecord(argumentsList).
  25. If hasDuplicates is true, then
    1. Perform ? IteratorBindingInitialization for formals with iteratorRecord and undefined as arguments.
  26. Else,
    1. Perform ? IteratorBindingInitialization for formals with iteratorRecord and env as arguments.
  27. If hasParameterExpressions is false, then
    1. NOTE: Only a single Environment Record is needed for the parameters and top-level vars.
    2. Let instantiatedVarNames be a copy of the List parameterBindings.
    3. For each element n of varNames, do
      1. If n is not an element of instantiatedVarNames, then
        1. Append n to instantiatedVarNames.
        2. Perform ! env.CreateMutableBinding(n, false).
        3. Call env.InitializeBinding(n, undefined).
    4. Let varEnv be env.
  28. 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. Set the VariableEnvironment of calleeContext to varEnv.
    4. Let instantiatedVarNames be a new empty List.
    5. For each element n of varNames, do
      1. If n is not an element of instantiatedVarNames, then
        1. Append n to instantiatedVarNames.
        2. Perform ! varEnv.CreateMutableBinding(n, false).
        3. If n is not an element of parameterBindings or if n is an element of functionNames, let initialValue be undefined.
        4. Else,
          1. Let initialValue be ! env.GetBindingValue(n, false).
        5. Call varEnv.InitializeBinding(n, initialValue).
        6. NOTE: A var with the same name as a formal parameter initially has the same value as the corresponding initialized parameter.
  29. NOTE: Annex B.3.3.1 adds additional steps at this point.
  30. If strict is false, then
    1. Let lexEnv be NewDeclarativeEnvironment(varEnv).
    2. NOTE: Non-strict functions use a separate Environment Record for top-level lexical declarations so that a direct eval 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.
  31. Else, let lexEnv be varEnv.
  32. Set the LexicalEnvironment of calleeContext to lexEnv.
  33. Let lexDeclarations be the LexicallyScopedDeclarations of code.
  34. For each element d of 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. Perform ! lexEnv.CreateImmutableBinding(dn, true).
      2. Else,
        1. Perform ! lexEnv.CreateMutableBinding(dn, false).
  35. For each Parse Node f of functionsToInitialize, do
    1. Let fn be the sole element of the BoundNames of f.
    2. Let fo be InstantiateFunctionObject of f with argument lexEnv.
    3. Perform ! varEnv.SetMutableBinding(fn, fo, false).
  36. Return NormalCompletion(empty).
Note 2

B.3.3 provides an extension to the above algorithm that is necessary for backwards compatibility with web browser implementations of ECMAScript that predate ECMAScript 2015.

Note 3

Parameter Initializers may contain direct eval expressions. Any top level declarations of such evals are only visible to the eval code (11.2). The creation of the environment for such declarations is described in 8.5.3.