Understanding ECMAScript Runtime Semantics, Algorithm Steps, and Abstract Operations
This article explains ECMAScript runtime semantics, detailing how algorithm steps and abstract operations such as ToBoolean and internal methods like [[GetPrototypeOf]] define JavaScript's execution behavior, and introduces related concepts like internal slots, completion records, and shorthand notations used in the specification.
This is the second article in the series "Understanding JavaScript from the ECMAScript language specification and browser engine perspective". The author recommends reading the series in order.
Runtime Semantics
Runtime semantics are defined by the ECMAScript specification as "algorithms which specify semantics that must be called at runtime". In practice, they describe what happens when a JavaScript API or syntax is invoked, such as Number('23') or a for‑in loop.
Most runtime semantics are expressed as a series of algorithm steps.
Algorithm Steps
Algorithm steps consist of a multi‑level ordered list whose numbering follows the pattern number → lowercase letter → lowercase Roman numeral. An example format is shown below:
1. Top‑level step
a. Substep.
b. Substep.
i. Subsubstep.
1. Subsubsubstep
a. Subsubsubsubstep
i. SubsubsubsubsubstepThese steps are pseudo‑code and do not represent a concrete implementation.
An example from the specification illustrates the algorithm steps for the Boolean(value) API, showing the sequence of operations performed when a value is converted to a boolean.
In the first step of that example, a function‑like call ToBoolean(value) appears; in the specification this is called an Abstract Operation .
Abstract Operations
Abstract operations are reusable algorithmic fragments, similar to functions in code. They are invoked in the spec with syntax like OperationName(arg1, arg2) . These operations are not part of the JavaScript language itself; they exist solely for specification purposes.
The ToBoolean abstract operation is shown in the following table (image).
It belongs to the "Type Conversion" category of abstract operations. Other categories include "Testing and Comparison Operations", "Operations on Objects", and "Operations on Iterator Objects".
[[ ]] Notation
The double‑bracket notation [[...]] appears throughout the spec to denote internal methods or internal slots. For example, V.[[GetPrototypeOf]] uses this notation to refer to an internal method.
Internal Methods
The actual semantics of objects in ECMAScript are specified via algorithms called internal methods . Each object in an ECMAScript engine is associated with a set of internal methods that defines its runtime behaviour.
Internal methods are polymorphic; the same method name may have different definitions for different object types. For an ordinary object, the internal method [[GetPrototypeOf]] is defined as shown in the following diagram (image).
The same internal method also has definitions for module‑namespace exotic objects and Proxy exotic objects.
Internal Slots
Internal slots store an object's internal state and are used by various specification algorithms. They are initialized to undefined and are not accessible as normal JavaScript properties, nor can they be inherited.
Although not reachable from code, some internal slots become visible in debugging tools, such as the [[Prototype]] slot that represents an object's prototype.
When Object.getPrototypeOf() is called, the engine actually returns the value of the internal slot O.[[Prototype]] .
Symbols ? and !
The spec frequently uses the symbols ? and ! as shorthand notations, not as JavaScript operators. They are related to the concept of a Completion Record .
Completion Record
The Completion Record specification type is used to explain the runtime propagation of values and control flow such as the behaviour of statements ( break , continue , return , and throw ) that perform non‑local transfers of control.
Completion records have five types: normal, break, continue, return, and throw. An abrupt completion is any type other than normal. The spec also defines shorthand names: "abrupt completion" and "a normal completion containing some type of value" (i.e., a normal completion whose [[Value]] field holds a value).
Normal completions are the most common; every abstract operation implicitly returns a normal completion that wraps its return value, as illustrated below:
1. Return true.
⬇ equivalent to ⬇
1. Return NormalCompletion(true).
// NormalCompletion structure
{
Type: normal,
Value: value,
Target: empty
}ReturnIfAbrupt
The ? symbol in the spec is a shorthand for the algorithm ReturnIfAbrupt . This algorithm checks a completion record: if it is an abrupt completion, the record is returned; otherwise the algorithm extracts the [[Value]] from a normal completion.
Let obj be Foo() . (obj is a Completion Record.) ReturnIfAbrupt(obj). Bar(obj) . (If we’re still here, obj is the value extracted from the Completion Record.)
Thus, after ReturnIfAbrupt , a normal completion’s obj becomes obj.[[Value]] , the actual value.
Shorthand ? and !
For convenience, the spec defines the following equivalences:
? OperationName() is equivalent to ReturnIfAbrupt(OperationName()) .
! OperationName() is a stricter form that asserts the result is a normal completion before extracting its value.
Let val be OperationName(). Assert: val is a normal completion. Set val to val.Value.
These shorthands are used throughout the specification, including in the algorithm steps for Object.prototype.isPrototypeOf shown below:
# 20.1.3.3 Object.prototype.isPrototypeOf ( V )
This method performs the following steps when called:
1. If V is not an Object, return false.
2. Let O be ToObject(this value).
3. Assert: O is a Completion Record.
4. If O is an abrupt completion, return Completion(O).
5. Else, set O to O.[[Value]].
6. Repeat,
a. Set V to V.[[GetPrototypeOf]]().
b. Assert: V is a Completion Record.
c. If V is an abrupt completion, return Completion(V).
d. Else, set V to V.[[Value]].
e. If V is null return false
f. Let temp be SameValue(O, V).
g. Assert: temp is not an abrupt completion.
h. Set temp be temp.[[Value]].
i. If temp is true return trueIf you have further questions, feel free to leave a comment.
References
ECMAScript Specification
How to Read the ECMAScript Specification
Understanding the ECMAScript spec, part 1
Rare Earth Juejin Tech Community
Juejin, a tech community that helps developers grow.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.