ECMAScript® 2024 Language Specification

Draft ECMA-262 / February 15, 2024

5.2 Algorithm Conventions

The specification often uses a numbered list to specify steps in an algorithm. These algorithms are used to precisely specify the required semantics of ECMAScript language constructs. The algorithms are not intended to imply the use of any specific implementation technique. In practice, there may be more efficient algorithms available to implement a given feature.

Algorithms may be explicitly parameterized with an ordered, comma-separated sequence of alias names which may be used within the algorithm steps to reference the argument passed in that position. Optional parameters are denoted with surrounding brackets ([ , name ]) and are no different from required parameters within algorithm steps. A rest parameter may appear at the end of a parameter list, denoted with leading ellipsis (, ...name). The rest parameter captures all of the arguments provided following the required and optional parameters into a List. If there are no such additional arguments, that List is empty.

Algorithm steps may be subdivided into sequential substeps. Substeps are indented and may themselves be further divided into indented substeps. Outline numbering conventions are used to identify substeps with the first level of substeps labelled with lowercase alphabetic characters and the second level of substeps labelled with lowercase roman numerals. If more than three levels are required these rules repeat with the fourth level using numeric labels. For example:

  1. Top-level step
    1. Substep.
    2. Substep.
      1. Subsubstep.
        1. Subsubsubstep
          1. Subsubsubsubstep
            1. Subsubsubsubsubstep

A step or substep may be written as an “if” predicate that conditions its substeps. In this case, the substeps are only applied if the predicate is true. If a step or substep begins with the word “else”, it is a predicate that is the negation of the preceding “if” predicate step at the same level.

A step may specify the iterative application of its substeps.

A step that begins with “Assert:” asserts an invariant condition of its algorithm. Such assertions are used to make explicit algorithmic invariants that would otherwise be implicit. Such assertions add no additional semantic requirements and hence need not be checked by an implementation. They are used simply to clarify algorithms.

Algorithm steps may declare named aliases for any value using the form “Let x be someValue”. These aliases are reference-like in that both x and someValue refer to the same underlying data and modifications to either are visible to both. Algorithm steps that want to avoid this reference-like behaviour should explicitly make a copy of the right-hand side: “Let x be a copy of someValue” creates a shallow copy of someValue.

Once declared, an alias may be referenced in any subsequent steps and must not be referenced from steps prior to the alias's declaration. Aliases may be modified using the form “Set x to someOtherValue”.

5.2.1 Abstract Operations

In order to facilitate their use in multiple parts of this specification, some algorithms, called abstract operations, are named and written in parameterized functional form so that they may be referenced by name from within other algorithms. Abstract operations are typically referenced using a functional application style such as OperationName(arg1, arg2). Some abstract operations are treated as polymorphically dispatched methods of class-like specification abstractions. Such method-like abstract operations are typically referenced using a method application style such as someValue.OperationName(arg1, arg2).

5.2.2 Syntax-Directed Operations

A syntax-directed operation is a named operation whose definition consists of algorithms, each of which is associated with one or more productions from one of the ECMAScript grammars. A production that has multiple alternative definitions will typically have a distinct algorithm for each alternative. When an algorithm is associated with a grammar production, it may reference the terminal and nonterminal symbols of the production alternative as if they were parameters of the algorithm. When used in this manner, nonterminal symbols refer to the actual alternative definition that is matched when parsing the source text. The source text matched by a grammar production or Parse Node derived from it is the portion of the source text that starts at the beginning of the first terminal that participated in the match and ends at the end of the last terminal that participated in the match.

When an algorithm is associated with a production alternative, the alternative is typically shown without any “[ ]” grammar annotations. Such annotations should only affect the syntactic recognition of the alternative and have no effect on the associated semantics for the alternative.

Syntax-directed operations are invoked with a parse node and, optionally, other parameters by using the conventions on steps 1, 3, and 4 in the following algorithm:

  1. Let status be SyntaxDirectedOperation of SomeNonTerminal.
  2. Let someParseNode be the parse of some source text.
  3. Perform SyntaxDirectedOperation of someParseNode.
  4. Perform SyntaxDirectedOperation of someParseNode with argument "value".

Unless explicitly specified otherwise, all chain productions have an implicit definition for every operation that might be applied to that production's left-hand side nonterminal. The implicit definition simply reapplies the same operation with the same parameters, if any, to the chain production's sole right-hand side nonterminal and then returns the result. For example, assume that some algorithm has a step of the form: “Return Evaluation of Block” and that there is a production:

Block : { StatementList }

but the Evaluation operation does not associate an algorithm with that production. In that case, the Evaluation operation implicitly includes an association of the form:

Runtime Semantics: Evaluation

Block : { StatementList }
  1. Return Evaluation of StatementList.

5.2.3 Runtime Semantics

Algorithms which specify semantics that must be called at runtime are called runtime semantics. Runtime semantics are defined by abstract operations or syntax-directed operations.

5.2.3.1 Completion ( completionRecord )

The abstract operation Completion takes argument completionRecord (a Completion Record) and returns a Completion Record. It is used to emphasize that a Completion Record is being returned. It performs the following steps when called:

  1. Assert: completionRecord is a Completion Record.
  2. Return completionRecord.

5.2.3.2 Throw an Exception

Algorithms steps that say to throw an exception, such as

  1. Throw a TypeError exception.

mean the same things as:

  1. Return ThrowCompletion(a newly created TypeError object).

5.2.3.3 ReturnIfAbrupt

Algorithms steps that say or are otherwise equivalent to:

  1. ReturnIfAbrupt(argument).

mean the same thing as:

  1. Assert: argument is a Completion Record.
  2. If argument is an abrupt completion, return Completion(argument).
  3. Else, set argument to argument.[[Value]].

Algorithms steps that say or are otherwise equivalent to:

  1. ReturnIfAbrupt(AbstractOperation()).

mean the same thing as:

  1. Let hygienicTemp be AbstractOperation().
  2. Assert: hygienicTemp is a Completion Record.
  3. If hygienicTemp is an abrupt completion, return Completion(hygienicTemp).
  4. Else, set hygienicTemp to hygienicTemp.[[Value]].

Where hygienicTemp is ephemeral and visible only in the steps pertaining to ReturnIfAbrupt.

Algorithms steps that say or are otherwise equivalent to:

  1. Let result be AbstractOperation(ReturnIfAbrupt(argument)).

mean the same thing as:

  1. Assert: argument is a Completion Record.
  2. If argument is an abrupt completion, return Completion(argument).
  3. Else, set argument to argument.[[Value]].
  4. Let result be AbstractOperation(argument).

5.2.3.4 ReturnIfAbrupt Shorthands

Invocations of abstract operations and syntax-directed operations that are prefixed by ? indicate that ReturnIfAbrupt should be applied to the resulting Completion Record. For example, the step:

  1. ? OperationName().

is equivalent to the following step:

  1. ReturnIfAbrupt(OperationName()).

Similarly, for method application style, the step:

  1. someValue.OperationName().

is equivalent to:

  1. ReturnIfAbrupt(someValue.OperationName()).

Similarly, prefix ! is used to indicate that the following invocation of an abstract or syntax-directed operation will never return an abrupt completion and that the resulting Completion Record's [[Value]] field should be used in place of the return value of the operation. For example, the step:

  1. Let val be ! OperationName().

is equivalent to the following steps:

  1. Let val be OperationName().
  2. Assert: val is a normal completion.
  3. Set val to val.[[Value]].

Syntax-directed operations for runtime semantics make use of this shorthand by placing ! or ? before the invocation of the operation:

  1. Perform ! SyntaxDirectedOperation of NonTerminal.

5.2.3.5 Implicit Normal Completion

In algorithms within abstract operations which are declared to return a Completion Record, and within all built-in functions, the returned value is first passed to NormalCompletion, and the result is used instead. This rule does not apply within the Completion algorithm or when the value being returned is clearly marked as a Completion Record in that step; these cases are:

It is an editorial error if a Completion Record is returned from such an abstract operation through any other means. For example, within these abstract operations,

  1. Return true.

means the same things as any of

  1. Return NormalCompletion(true).

or

  1. Let completion be NormalCompletion(true).
  2. Return Completion(completion).

or

  1. Return Completion Record { [[Type]]: normal, [[Value]]: true, [[Target]]: empty }.

Note that, through the ReturnIfAbrupt expansion, the following example is allowed, as within the expanded steps, the result of applying Completion is returned directly in the abrupt case and the implicit NormalCompletion application occurs after unwrapping in the normal case.

  1. Return ? completion.

The following example would be an editorial error because a Completion Record is being returned without being annotated in that step.

  1. Let completion be NormalCompletion(true).
  2. Return completion.

5.2.4 Static Semantics

Context-free grammars are not sufficiently powerful to express all the rules that define whether a stream of input elements form a valid ECMAScript Script or Module that may be evaluated. In some situations additional rules are needed that may be expressed using either ECMAScript algorithm conventions or prose requirements. Such rules are always associated with a production of a grammar and are called the static semantics of the production.

Static Semantic Rules have names and typically are defined using an algorithm. Named Static Semantic Rules are associated with grammar productions and a production that has multiple alternative definitions will typically have for each alternative a distinct algorithm for each applicable named static semantic rule.

A special kind of static semantic rule is an Early Error Rule. Early error rules define early error conditions (see clause 17) that are associated with specific grammar productions. Evaluation of most early error rules are not explicitly invoked within the algorithms of this specification. A conforming implementation must, prior to the first evaluation of a Script or Module, validate all of the early error rules of the productions used to parse that Script or Module. If any of the early error rules are violated the Script or Module is invalid and cannot be evaluated.

5.2.5 Mathematical Operations

This specification makes reference to these kinds of numeric values:

In the language of this specification, numerical values are distinguished among different numeric kinds using subscript suffixes. The subscript 𝔽 refers to Numbers, and the subscript refers to BigInts. Numeric values without a subscript suffix refer to mathematical values.

Numeric operators such as +, ×, =, and ≥ refer to those operations as determined by the type of the operands. When applied to mathematical values, the operators refer to the usual mathematical operations. When applied to extended mathematical values, the operators refer to the usual mathematical operations over the extended real numbers; indeterminate forms are not defined and their use in this specification should be considered an editorial error. When applied to Numbers, the operators refer to the relevant operations within IEEE 754-2019. When applied to BigInts, the operators refer to the usual mathematical operations applied to the mathematical value of the BigInt.

In general, when this specification refers to a numerical value, such as in the phrase, "the length of y" or "the integer represented by the four hexadecimal digits ...", without explicitly specifying a numeric kind, the phrase refers to a mathematical value. Phrases which refer to a Number or a BigInt value are explicitly annotated as such; for example, "the Number value for the number of code points in …" or "the BigInt value for …".

Numeric operators applied to mixed-type operands (such as a Number and a mathematical value) are not defined and should be considered an editorial error in this specification.

This specification denotes most numeric values in base 10; it also uses numeric values of the form 0x followed by digits 0-9 or A-F as base-16 values.

When the term integer is used in this specification, it refers to a mathematical value which is in the set of integers, unless otherwise stated. When the term integral Number is used in this specification, it refers to a Number value whose mathematical value is in the set of integers.

Conversions between mathematical values and Numbers or BigInts are always explicit in this document. A conversion from a mathematical value or extended mathematical value x to a Number is denoted as "the Number value for x" or 𝔽(x), and is defined in 6.1.6.1. A conversion from an integer x to a BigInt is denoted as "the BigInt value for x" or ℤ(x). A conversion from a Number or BigInt x to a mathematical value is denoted as "the mathematical value of x", or ℝ(x). The mathematical value of +0𝔽 and -0𝔽 is the mathematical value 0. The mathematical value of non-finite values is not defined. The extended mathematical value of x is the mathematical value of x for finite values, and is +∞ and -∞ for +∞𝔽 and -∞𝔽 respectively; it is not defined for NaN.

The mathematical function abs(x) produces the absolute value of x, which is -x if x < 0 and otherwise is x itself.

The mathematical function min(x1, x2, … , xN) produces the mathematically smallest of x1 through xN. The mathematical function max(x1, x2, ..., xN) produces the mathematically largest of x1 through xN. The domain and range of these mathematical functions are the extended mathematical values.

The notation “x modulo y” (y must be finite and non-zero) computes a value k of the same sign as y (or zero) such that abs(k) < abs(y) and x - k = q × y for some integer q.

The phrase "the result of clamping x between lower and upper" (where x is an extended mathematical value and lower and upper are mathematical values such that lowerupper) produces lower if x < lower, produces upper if x > upper, and otherwise produces x.

The mathematical function floor(x) produces the largest integer (closest to +∞) that is not larger than x.

Note

floor(x) = x - (x modulo 1).

The mathematical function truncate(x) removes the fractional part of x by rounding towards zero, producing -floor(-x) if x < 0 and otherwise producing floor(x).

Mathematical functions min, max, abs, floor, and truncate are not defined for Numbers and BigInts, and any usage of those methods that have non-mathematical value arguments would be an editorial error in this specification.

An interval from lower bound a to upper bound b is a possibly-infinite, possibly-empty set of numeric values of the same numeric type. Each bound will be described as either inclusive or exclusive, but not both. There are four kinds of intervals, as follows:

  • An interval from a (inclusive) to b (inclusive), also called an inclusive interval from a to b, includes all values x of the same numeric type such that axb, and no others.
  • An interval from a (inclusive) to b (exclusive) includes all values x of the same numeric type such that ax < b, and no others.
  • An interval from a (exclusive) to b (inclusive) includes all values x of the same numeric type such that a < xb, and no others.
  • An interval from a (exclusive) to b (exclusive) includes all values x of the same numeric type such that a < x < b, and no others.

For example, the interval from 1 (inclusive) to 2 (exclusive) consists of all mathematical values between 1 and 2, including 1 and not including 2. For the purpose of defining intervals, -0𝔽 < +0𝔽, so, for example, an inclusive interval with a lower bound of +0𝔽 includes +0𝔽 but not -0𝔽. NaN is never included in an interval.

5.2.6 Value Notation

In this specification, ECMAScript language values are displayed in bold. Examples include null, true, or "hello". These are distinguished from ECMAScript source text such as Function.prototype.apply or let n = 42;.

5.2.7 Identity

In this specification, both specification values and ECMAScript language values are compared for equality. When comparing for equality, values fall into one of two categories. Values without identity are equal to other values without identity if all of their innate characteristics are the same — characteristics such as the magnitude of an integer or the length of a sequence. Values without identity may be manifest without prior reference by fully describing their characteristics. In contrast, each value with identity is unique and therefore only equal to itself. Values with identity are like values without identity but with an additional unguessable, unchangeable, universally-unique characteristic called identity. References to existing values with identity cannot be manifest simply by describing them, as the identity itself is indescribable; instead, references to these values must be explicitly passed from one place to another. Some values with identity are mutable and therefore can have their characteristics (except their identity) changed in-place, causing all holders of the value to observe the new characteristics. A value without identity is never equal to a value with identity.

From the perspective of this specification, the word “is” is used to compare two values for equality, as in “If bool is true, then ...”, and the word “contains” is used to search for a value inside lists using equality comparisons, as in "If list contains a Record r such that r.[[Foo]] is true, then ...". The specification identity of values determines the result of these comparisons and is axiomatic in this specification.

From the perspective of the ECMAScript language, language values are compared for equality using the SameValue abstract operation and the abstract operations it transitively calls. The algorithms of these comparison abstract operations determine language identity of ECMAScript language values.

For specification values, examples of values without specification identity include, but are not limited to: mathematical values and extended mathematical values; ECMAScript source text, surrogate pairs, Directive Prologues, etc; UTF-16 code units; Unicode code points; enums; abstract operations, including syntax-directed operations, host hooks, etc; and ordered pairs. Examples of specification values with specification identity include, but are not limited to: any kind of Records, including Property Descriptors, PrivateElements, etc; Parse Nodes; Lists; Sets and Relations; Abstract Closures; Data Blocks; Private Names; execution contexts and execution context stacks; agent signifiers; and WaiterList Records.

Specification identity agrees with language identity for all ECMAScript language values except Symbol values produced by Symbol.for. The ECMAScript language values without specification identity and without language identity are undefined, null, Booleans, Strings, Numbers, and BigInts. The ECMAScript language values with specification identity and language identity are Symbols not produced by Symbol.for and Objects. Symbol values produced by Symbol.for have specification identity, but not language identity.