From 35a7d357993d1faaf672fb543ca2b0b604af45a9 Mon Sep 17 00:00:00 2001 From: Alexey Shvayka Date: Wed, 28 Oct 2020 15:41:52 -0700 Subject: [PATCH] Editorial: Make Reference type a Record value (#2085) Resolves #333. --- spec.html | 205 ++++++++++++++++++++++++++++-------------------------- 1 file changed, 105 insertions(+), 100 deletions(-) diff --git a/spec.html b/spec.html index 23857ed25e..4d432ccab8 100644 --- a/spec.html +++ b/spec.html @@ -3547,7 +3547,7 @@

The Set and Relation Specification Types

The Completion Record Specification Type

The Completion type is a Record used to explain the runtime propagation of values and control flow such as the behaviour of statements (`break`, `continue`, `return` and `throw`) that perform nonlocal transfers of control.

-

Values of the Completion type are Record values whose fields are defined as by . Such values are referred to as Completion Records.

+

Values of the Completion type are Record values whose fields are defined by . Such values are referred to as Completion Records.

@@ -3718,57 +3718,65 @@

UpdateEmpty ( _completionRecord_, _value_ )

- -

The Reference Specification Type

- -

The Reference type is used to explain the behaviour of such operators as `delete`, `typeof`, the assignment operators, the `super` keyword and other language features. For example, the left-hand operand of an assignment is expected to produce a reference.

-
-

A Reference is a resolved name or property binding. A Reference consists of three components, the base value component, the referenced name component, and the Boolean-valued strict reference flag. The base value component is either *undefined*, an Object, a Boolean, a String, a Symbol, a Number, a BigInt, or an Environment Record. A base value component of *undefined* indicates that the Reference could not be resolved to a binding. The referenced name component is a String or Symbol value.

-

A Super Reference is a Reference that is used to represent a name binding that was expressed using the super keyword. A Super Reference has an additional thisValue component, and its base value component will never be an Environment Record.

-

The following abstract operations are used in this specification to operate on references:

- - -

GetBase ( _V_ )

-

The abstract operation GetBase takes argument _V_. It performs the following steps when called:

- - 1. Assert: Type(_V_) is Reference. - 1. Return the base value component of _V_. - -
+ +

The Reference Record Specification Type

+

The Reference Record type is used to explain the behaviour of such operators as `delete`, `typeof`, the assignment operators, the `super` keyword and other language features. For example, the left-hand operand of an assignment is expected to produce a Reference Record.

+

A Reference Record is a resolved name or property binding; its fields are defined by .

- -

GetReferencedName ( _V_ )

-

The abstract operation GetReferencedName takes argument _V_. It performs the following steps when called:

- - 1. Assert: Type(_V_) is Reference. - 1. Return the referenced name component of _V_. - -
- - -

IsStrictReference ( _V_ )

-

The abstract operation IsStrictReference takes argument _V_. It performs the following steps when called:

- - 1. Assert: Type(_V_) is Reference. - 1. Return the strict reference flag of _V_. - -
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
Field NameValueMeaning
[[Base]] + One of: +
    +
  • + any ECMAScript language value except *undefined* or *null*, +
  • +
  • + an Environment Record, or +
  • +
  • + ~unresolvable~. +
  • +
+
The value or Environment Record which holds the binding. A [[Base]] of ~unresolvable~ indicates that the binding could not be resolved.
[[ReferencedName]]String or SymbolThe name of the binding. Always a String if [[Base]] value is an Environment Record.
[[Strict]]Boolean*true* if the Reference Record originated in strict mode code, *false* otherwise.
[[ThisValue]]any ECMAScript language value or ~empty~If not ~empty~, the Reference Record represents a property binding that was expressed using the `super` keyword; it is called a Super Reference Record and its [[Base]] value will never be an Environment Record. In that case, the [[ThisValue]] field holds the *this* value at the time the Reference Record was created.
+
- -

HasPrimitiveBase ( _V_ )

-

The abstract operation HasPrimitiveBase takes argument _V_. It performs the following steps when called:

- - 1. Assert: Type(_V_) is Reference. - 1. If Type(_V_'s base value component) is Boolean, String, Symbol, BigInt, or Number, return *true*; otherwise return *false*. - -
+

The following abstract operations are used in this specification to operate upon References:

IsPropertyReference ( _V_ )

The abstract operation IsPropertyReference takes argument _V_. It performs the following steps when called:

- 1. Assert: Type(_V_) is Reference. - 1. If either the base value component of _V_ is an Object or HasPrimitiveBase(_V_) is *true*, return *true*; otherwise return *false*. + 1. Assert: _V_ is a Reference Record. + 1. If _V_.[[Base]] is ~unresolvable~, return *false*. + 1. If Type(_V_.[[Base]]) is Boolean, String, Symbol, BigInt, Number, or Object, return *true*; otherwise return *false*.
@@ -3776,8 +3784,8 @@

IsPropertyReference ( _V_ )

IsUnresolvableReference ( _V_ )

The abstract operation IsUnresolvableReference takes argument _V_. It performs the following steps when called:

- 1. Assert: Type(_V_) is Reference. - 1. If the base value component of _V_ is *undefined*, return *true*; otherwise return *false*. + 1. Assert: _V_ is a Reference Record. + 1. If _V_.[[Base]] is ~unresolvable~, return *true*; otherwise return *false*.
@@ -3785,8 +3793,8 @@

IsUnresolvableReference ( _V_ )

IsSuperReference ( _V_ )

The abstract operation IsSuperReference takes argument _V_. It performs the following steps when called:

- 1. Assert: Type(_V_) is Reference. - 1. If _V_ has a thisValue component, return *true*; otherwise return *false*. + 1. Assert: _V_ is a Reference Record. + 1. If _V_.[[ThisValue]] is not ~empty~, return *true*; otherwise return *false*. @@ -3795,17 +3803,15 @@

GetValue ( _V_ )

The abstract operation GetValue takes argument _V_. It performs the following steps when called:

1. ReturnIfAbrupt(_V_). - 1. If Type(_V_) is not Reference, return _V_. - 1. Let _base_ be GetBase(_V_). + 1. If _V_ is not a Reference Record, return _V_. 1. If IsUnresolvableReference(_V_) is *true*, throw a *ReferenceError* exception. 1. If IsPropertyReference(_V_) is *true*, then - 1. If HasPrimitiveBase(_V_) is *true*, then - 1. Assert: In this case, _base_ will never be *undefined* or *null*. - 1. [id="step-getvalue-toobject"] Set _base_ to ! ToObject(_base_). - 1. Return ? _base_.[[Get]](GetReferencedName(_V_), GetThisValue(_V_)). + 1. [id="step-getvalue-toobject"] Let _baseObj_ be ! ToObject(_V_.[[Base]]). + 1. Return ? _baseObj_.[[Get]](_V_.[[ReferencedName]], GetThisValue(_V_)). 1. Else, + 1. Let _base_ be _V_.[[Base]]. 1. Assert: _base_ is an Environment Record. - 1. Return ? _base_.GetBindingValue(GetReferencedName(_V_), IsStrictReference(_V_)) (see ). + 1. Return ? _base_.GetBindingValue(_V_.[[ReferencedName]], _V_.[[Strict]]) (see ).

The object that may be created in step is not accessible outside of the above abstract operation and the ordinary object [[Get]] internal method. An implementation might choose to avoid the actual creation of the object.

@@ -3818,23 +3824,20 @@

PutValue ( _V_, _W_ )

1. ReturnIfAbrupt(_V_). 1. ReturnIfAbrupt(_W_). - 1. If Type(_V_) is not Reference, throw a *ReferenceError* exception. - 1. Let _base_ be GetBase(_V_). + 1. If _V_ is not a Reference Record, throw a *ReferenceError* exception. 1. If IsUnresolvableReference(_V_) is *true*, then - 1. If IsStrictReference(_V_) is *true*, then - 1. Throw a *ReferenceError* exception. + 1. If _V_.[[Strict]] is *true*, throw a *ReferenceError* exception. 1. Let _globalObj_ be GetGlobalObject(). - 1. Return ? Set(_globalObj_, GetReferencedName(_V_), _W_, *false*). - 1. Else if IsPropertyReference(_V_) is *true*, then - 1. If HasPrimitiveBase(_V_) is *true*, then - 1. Assert: In this case, _base_ will never be *undefined* or *null*. - 1. [id="step-putvalue-toobject"] Set _base_ to ! ToObject(_base_). - 1. Let _succeeded_ be ? _base_.[[Set]](GetReferencedName(_V_), _W_, GetThisValue(_V_)). - 1. If _succeeded_ is *false* and IsStrictReference(_V_) is *true*, throw a *TypeError* exception. + 1. Return ? Set(_globalObj_, _V_.[[ReferencedName]], _W_, *false*). + 1. If IsPropertyReference(_V_) is *true*, then + 1. [id="step-putvalue-toobject"] Let _baseObj_ be ! ToObject(_V_.[[Base]]). + 1. Let _succeeded_ be ? _baseObj_.[[Set]](_V_.[[ReferencedName]], _W_, GetThisValue(_V_)). + 1. If _succeeded_ is *false* and _V_.[[Strict]] is *true*, throw a *TypeError* exception. 1. Return. 1. Else, + 1. Let _base_ be _V_.[[Base]]. 1. Assert: _base_ is an Environment Record. - 1. Return ? _base_.SetMutableBinding(GetReferencedName(_V_), _W_, IsStrictReference(_V_)) (see ). + 1. Return ? _base_.SetMutableBinding(_V_.[[ReferencedName]], _W_, _V_.[[Strict]]) (see ).

The object that may be created in step is not accessible outside of the above abstract operation and the ordinary object [[Set]] internal method. An implementation might choose to avoid the actual creation of that object.

@@ -3846,9 +3849,7 @@

GetThisValue ( _V_ )

The abstract operation GetThisValue takes argument _V_. It performs the following steps when called:

1. Assert: IsPropertyReference(_V_) is *true*. - 1. If IsSuperReference(_V_) is *true*, then - 1. Return the value of the thisValue component of the reference _V_. - 1. Return GetBase(_V_). + 1. If IsSuperReference(_V_) is *true*, return _V_.[[ThisValue]]; otherwise return _V_.[[Base]]. @@ -3858,11 +3859,11 @@

InitializeReferencedBinding ( _V_, _W_ )

1. ReturnIfAbrupt(_V_). 1. ReturnIfAbrupt(_W_). - 1. Assert: Type(_V_) is Reference. + 1. Assert: _V_ is a Reference Record. 1. Assert: IsUnresolvableReference(_V_) is *false*. - 1. Let _base_ be GetBase(_V_). + 1. Let _base_ be _V_.[[Base]]. 1. Assert: _base_ is an Environment Record. - 1. Return _base_.InitializeBinding(GetReferencedName(_V_), _W_). + 1. Return _base_.InitializeBinding(_V_.[[ReferencedName]], _W_). @@ -6750,7 +6751,7 @@

DeleteBinding ( _N_ )

1. Assert: This method is never invoked. See . -

Module Environment Records are only used within strict code and an early error rule prevents the delete operator, in strict code, from being applied to a Reference that would resolve to a module Environment Record binding. See .

+

Module Environment Records are only used within strict code and an early error rule prevents the delete operator, in strict code, from being applied to a Reference Record that would resolve to a module Environment Record binding. See .

@@ -6793,10 +6794,10 @@

GetIdentifierReference ( _env_, _name_, _strict_ )

The abstract operation GetIdentifierReference takes arguments _env_ (an Environment Record or *null*), _name_ (a String), and _strict_ (a Boolean). It performs the following steps when called:

1. If _env_ is the value *null*, then - 1. Return a value of type Reference whose base value component is *undefined*, whose referenced name component is _name_, and whose strict reference flag is _strict_. + 1. Return the Reference Record { [[Base]]: ~unresolvable~, [[ReferencedName]]: _name_, [[Strict]]: _strict_, [[ThisValue]]: ~empty~ }. 1. Let _exists_ be ? _env_.HasBinding(_name_). 1. If _exists_ is *true*, then - 1. Return a value of type Reference whose base value component is _env_, whose referenced name component is _name_, and whose strict reference flag is _strict_. + 1. Return the Reference Record { [[Base]]: _env_, [[ReferencedName]]: _name_, [[Strict]]: _strict_, [[ThisValue]]: ~empty~ }. 1. Else, 1. Let _outer_ be _env_.[[OuterEnv]]. 1. Return ? GetIdentifierReference(_outer_, _name_, _strict_). @@ -7135,7 +7136,7 @@

ResolveBinding ( _name_ [ , _env_ ] )

1. Return ? GetIdentifierReference(_env_, _name_, _strict_).
-

The result of ResolveBinding is always a Reference value with its referenced name component equal to the _name_ argument.

+

The result of ResolveBinding is always a Reference Record whose [[ReferencedName]] field is _name_.

@@ -13556,7 +13557,7 @@

EvaluatePropertyAccessWithExpressionKey ( _baseValue_, _expression_, _strict 1. Let _propertyNameValue_ be ? GetValue(_propertyNameReference_). 1. Let _bv_ be ? RequireObjectCoercible(_baseValue_). 1. Let _propertyKey_ be ? ToPropertyKey(_propertyNameValue_). - 1. Return a value of type Reference whose base value component is _bv_, whose referenced name component is _propertyKey_, and whose strict reference flag is _strict_. + 1. Return the Reference Record { [[Base]]: _bv_, [[ReferencedName]]: _propertyKey_, [[Strict]]: _strict_, [[ThisValue]]: ~empty~ }. @@ -13566,7 +13567,7 @@

EvaluatePropertyAccessWithIdentifierKey ( _baseValue_, _identifierName_, _st 1. Assert: _identifierName_ is an |IdentifierName|. 1. Let _bv_ be ? RequireObjectCoercible(_baseValue_). 1. Let _propertyNameString_ be StringValue of _identifierName_. - 1. Return a value of type Reference whose base value component is _bv_, whose referenced name component is _propertyNameString_, and whose strict reference flag is _strict_. + 1. Return the Reference Record { [[Base]]: _bv_, [[ReferencedName]]: _propertyNameString_, [[Strict]]: _strict_, [[ThisValue]]: ~empty~ }. @@ -13614,7 +13615,7 @@

Runtime Semantics: Evaluation

1. Let _arguments_ be the |Arguments| of _expr_. 1. Let _ref_ be the result of evaluating _memberExpr_. 1. Let _func_ be ? GetValue(_ref_). - 1. If Type(_ref_) is Reference, IsPropertyReference(_ref_) is *false*, and GetReferencedName(_ref_) is *"eval"*, then + 1. If _ref_ is a Reference Record, IsPropertyReference(_ref_) is *false*, and _ref_.[[ReferencedName]] is *"eval"*, then 1. If SameValue(_func_, %eval%) is *true*, then 1. Let _argList_ be ? ArgumentListEvaluation of _arguments_. 1. If _argList_ has no elements, return *undefined*. @@ -13641,12 +13642,12 @@

Runtime Semantics: Evaluation

EvaluateCall ( _func_, _ref_, _arguments_, _tailPosition_ )

The abstract operation EvaluateCall takes arguments _func_ (an ECMAScript language value), _ref_ (an ECMAScript language value), _arguments_ (a Parse Node), and _tailPosition_ (a Boolean). It performs the following steps when called:

- 1. If Type(_ref_) is Reference, then + 1. If _ref_ is a Reference Record, then 1. If IsPropertyReference(_ref_) is *true*, then 1. Let _thisValue_ be GetThisValue(_ref_). 1. Else, - 1. Assert: the base of _ref_ is an Environment Record. - 1. Let _refEnv_ be GetBase(_ref_). + 1. Let _refEnv_ be _ref_.[[Base]]. + 1. Assert: _refEnv_ is an Environment Record. 1. Let _thisValue_ be _refEnv_.WithBaseObject(). 1. Else, 1. Let _thisValue_ be *undefined*. @@ -13719,7 +13720,8 @@

MakeSuperPropertyReference ( _actualThis_, _propertyKey_, _strict_ )

1. Assert: _env_.HasSuperBinding() is *true*. 1. Let _baseValue_ be ? _env_.GetSuperBase(). 1. Let _bv_ be ? RequireObjectCoercible(_baseValue_). - 1. Return a value of type Reference that is a Super Reference whose base value component is _bv_, whose referenced name component is _propertyKey_, whose thisValue component is _actualThis_, and whose strict reference flag is _strict_. + 1. Return the Reference Record { [[Base]]: _bv_, [[ReferencedName]]: _propertyKey_, [[Strict]]: _strict_, [[ThisValue]]: _actualThis_ }. + 1. NOTE: This returns a Super Reference Record.
@@ -14185,24 +14187,27 @@

Runtime Semantics: Evaluation

1. Let _ref_ be the result of evaluating |UnaryExpression|. 1. ReturnIfAbrupt(_ref_). - 1. If Type(_ref_) is not Reference, return *true*. + 1. If _ref_ is not a Reference Record, return *true*. 1. If IsUnresolvableReference(_ref_) is *true*, then - 1. Assert: IsStrictReference(_ref_) is *false*. + 1. Assert: _ref_.[[Strict]] is *false*. 1. Return *true*. 1. If IsPropertyReference(_ref_) is *true*, then 1. If IsSuperReference(_ref_) is *true*, throw a *ReferenceError* exception. - 1. Let _baseObj_ be ! ToObject(GetBase(_ref_)). - 1. Let _deleteStatus_ be ? _baseObj_.[[Delete]](GetReferencedName(_ref_)). - 1. If _deleteStatus_ is *false* and IsStrictReference(_ref_) is *true*, throw a *TypeError* exception. + 1. [id="step-delete-operator-toobject"] Let _baseObj_ be ! ToObject(_ref_.[[Base]]). + 1. Let _deleteStatus_ be ? _baseObj_.[[Delete]](_ref_.[[ReferencedName]]). + 1. If _deleteStatus_ is *false* and _ref_.[[Strict]] is *true*, throw a *TypeError* exception. 1. Return _deleteStatus_. 1. Else, - 1. Assert: _ref_ is a Reference to an Environment Record binding. - 1. Let _bindings_ be GetBase(_ref_). - 1. Return ? _bindings_.DeleteBinding(GetReferencedName(_ref_)). + 1. Let _base_ be _ref_.[[Base]]. + 1. Assert: _base_ is an Environment Record. + 1. Return ? _base_.DeleteBinding(_ref_.[[ReferencedName]]).

When a `delete` operator occurs within strict mode code, a *SyntaxError* exception is thrown if its |UnaryExpression| is a direct reference to a variable, function argument, or function name. In addition, if a `delete` operator occurs within strict mode code and the property to be deleted has the attribute { [[Configurable]]: *false* } (or otherwise cannot be deleted), a *TypeError* exception is thrown.

+ +

The object that may be created in step is not accessible outside of the above abstract operation and the ordinary object [[Delete]] internal method. An implementation might choose to avoid the actual creation of that object.

+
@@ -14231,7 +14236,7 @@

Runtime Semantics: Evaluation

UnaryExpression : `typeof` UnaryExpression 1. Let _val_ be the result of evaluating |UnaryExpression|. - 1. If Type(_val_) is Reference, then + 1. If _val_ is a Reference Record, then 1. If IsUnresolvableReference(_val_) is *true*, return *"undefined"*. 1. Set _val_ to ? GetValue(_val_). 1. Return a String according to . @@ -15193,7 +15198,7 @@

Runtime Semantics: Evaluation

1. Let _lref_ be the result of evaluating |LeftHandSideExpression|. 1. ReturnIfAbrupt(_lref_). 1. If IsAnonymousFunctionDefinition(|AssignmentExpression|) and IsIdentifierRef of |LeftHandSideExpression| are both *true*, then - 1. Let _rval_ be NamedEvaluation of |AssignmentExpression| with argument GetReferencedName(_lref_). + 1. Let _rval_ be NamedEvaluation of |AssignmentExpression| with argument _lref_.[[ReferencedName]]. 1. Else, 1. Let _rref_ be the result of evaluating |AssignmentExpression|. 1. Let _rval_ be ? GetValue(_rref_). @@ -15616,7 +15621,7 @@

Runtime Semantics: IteratorDestructuringAssignmentEvaluation

1. If _iteratorRecord_.[[Done]] is *true*, let _value_ be *undefined*. 1. If |Initializer| is present and _value_ is *undefined*, then 1. If IsAnonymousFunctionDefinition(|Initializer|) is *true* and IsIdentifierRef of |DestructuringAssignmentTarget| is *true*, then - 1. Let _v_ be NamedEvaluation of |Initializer| with argument GetReferencedName(_lref_). + 1. Let _v_ be NamedEvaluation of |Initializer| with argument _lref_.[[ReferencedName]]. 1. Else, 1. Let _defaultValue_ be the result of evaluating |Initializer|. 1. Let _v_ be ? GetValue(_defaultValue_). @@ -15665,7 +15670,7 @@

Runtime Semantics: KeyedDestructuringAssignmentEvaluation

1. Let _v_ be ? GetV(_value_, _propertyName_). 1. If |Initializer| is present and _v_ is *undefined*, then 1. If IsAnonymousFunctionDefinition(|Initializer|) and IsIdentifierRef of |DestructuringAssignmentTarget| are both *true*, then - 1. Let _rhsValue_ be NamedEvaluation of |Initializer| with argument GetReferencedName(_lref_). + 1. Let _rhsValue_ be NamedEvaluation of |Initializer| with argument _lref_.[[ReferencedName]]. 1. Else, 1. Let _defaultValue_ be the result of evaluating |Initializer|. 1. Let _rhsValue_ be ? GetValue(_defaultValue_). @@ -21961,7 +21966,7 @@

Statement Rules

Expression Rules

-

A potential tail position call that is immediately followed by return GetValue of the call result is also a possible tail position call. Function calls cannot return reference values, so such a GetValue operation will always return the same value as the actual function call result.

+

A potential tail position call that is immediately followed by return GetValue of the call result is also a possible tail position call. A function call cannot return a Reference Record, so such a GetValue operation will always return the same value as the actual function call result.

AssignmentExpression : @@ -26815,7 +26820,7 @@

RangeError

ReferenceError

The ReferenceError constructor is %ReferenceError%.

-

Indicate that an invalid reference value has been detected.

+

Indicate that an invalid reference has been detected.

@@ -43302,7 +43307,7 @@

Corrections and Clarifications in ECMAScript 2015 with Possible Compatibilit

Additions and Changes That Introduce Incompatibilities with Prior Editions

-

: In ECMAScript 2015, Function calls are not allowed to return a Reference value.

+

: In ECMAScript 2015, Function calls are not allowed to return a Reference Record.

: In ECMAScript 2015, ToNumber applied to a String value now recognizes and converts |BinaryIntegerLiteral| and |OctalIntegerLiteral| numeric strings. In previous editions such strings were converted to *NaN*.

: In ECMAScript 2018, Template objects are canonicalized based on Parse Node (source location), instead of across all occurrences of that template literal or tagged template in a Realm in previous editions.

: In ECMASCript 2016, Unicode 8.0.0 or higher is mandated, as opposed to ECMAScript 2015 which mandated Unicode 5.1. In particular, this caused U+180E MONGOLIAN VOWEL SEPARATOR, which was in the `Space_Separator` (`Zs`) category and thus treated as whitespace in ECMAScript 2015, to be moved to the `Format` (`Cf`) category (as of Unicode 6.3.0). This causes whitespace-sensitive methods to behave differently. For example, `"\u180E".trim().length` was `0` in previous editions, but `1` in ECMAScript 2016 and later. Additionally, ECMAScript 2017 mandated always using the latest version of the Unicode standard.