From fe7b168302411028e9a1388f1af6b2bf0dd2ba8a Mon Sep 17 00:00:00 2001 From: Michael Dyck Date: Sun, 24 Jan 2021 00:30:29 -0500 Subject: [PATCH] Editorial: Model a binding as a Record --- spec.html | 179 ++++++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 153 insertions(+), 26 deletions(-) diff --git a/spec.html b/spec.html index 37c004f6b6c..109bdaa068b 100644 --- a/spec.html +++ b/spec.html @@ -8744,22 +8744,108 @@

Declarative Environment Records

[[Bindings]] - List of bindings + List of DeclarativeBindingRecord - Satisfies the invariant that no two bindings in [[Bindings]] are bindings for the same name. + Satisfies the invariant that no two records in [[Bindings]] have the same [[BoundName]]. + +

A DeclarativeBindingRecord has the following fields:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ Field Name + + Value + + Meaning +
+ [[BoundName]] + + a String + + the name being bound. +
+ [[IsInitialized]] + + a Boolean + + indicates whether the binding is initialized. +
+ [[BoundValue]] + + an ECMAScript language value + + the value that the name is bound to. +
+ [[IsMutable]] + + a Boolean + + if *true*, indicates that the binding is mutable. +
+ [[IsDeletable]] + + a Boolean + + if *true*, indicates that the binding may be deleted by a subsequent DeleteBinding call. +
+ [[IsStrict]] + + a Boolean + + if *true*, indicates that the binding is a strict binding. +
+
+

The behaviour of the concrete specification methods for declarative Environment Records is defined by the following algorithms.

HasBinding ( _N_ )

The HasBinding concrete method of a declarative Environment Record _envRec_ takes argument _N_ (a String). It determines if the argument identifier is one of the identifiers bound by the record. It performs the following steps when called:

- 1. If _envRec_.[[Bindings]] contains a binding for the name that is the value of _N_, return *true*. + 1. If _envRec_.[[Bindings]] contains a DeclarativeBindingRecord whose [[BoundName]] field is equal to the value of _N_, return *true*. 1. Return *false*.
@@ -8769,7 +8855,7 @@

CreateMutableBinding ( _N_, _D_ )

The CreateMutableBinding concrete method of a declarative Environment Record _envRec_ takes arguments _N_ (a String) and _D_ (a Boolean). It creates a new mutable binding for the name _N_ that is uninitialized. A binding must not already exist in this Environment Record for _N_. If _D_ has the value *true*, the new binding is marked as being subject to deletion. It performs the following steps when called:

1. Assert: _envRec_.HasBinding(_N_) is *false*. - 1. Let _binding_ be a mutable binding for _N_ and record that it is uninitialized. If _D_ is *true*, record that the newly created binding may be deleted by a subsequent DeleteBinding call. + 1. Let _binding_ be DeclarativeBindingRecord { [[BoundName]]: _N_, [[IsInitialized]]: *false*, [[BoundValue]]: *undefined*, [[IsMutable]]: *true*, [[IsDeletable]]: _D_, [[IsStrict]]: *false* }. 1. Append _binding_ to _envRec_.[[Bindings]]. 1. Return NormalCompletion(~empty~). @@ -8780,7 +8866,7 @@

CreateImmutableBinding ( _N_, _S_ )

The CreateImmutableBinding concrete method of a declarative Environment Record _envRec_ takes arguments _N_ (a String) and _S_ (a Boolean). It creates a new immutable binding for the name _N_ that is uninitialized. A binding must not already exist in this Environment Record for _N_. If _S_ has the value *true*, the new binding is marked as a strict binding. It performs the following steps when called:

1. Assert: _envRec_.HasBinding(_N_) is *false*. - 1. Let _binding_ be an immutable binding for _N_ and record that it is uninitialized. If _S_ is *true*, record that the newly created binding is a strict binding. + 1. Let _binding_ be DeclarativeBindingRecord { [[BoundName]]: _N_, [[IsInitialized]]: *false*, [[BoundValue]]: *undefined*, [[IsMutable]]: *false*, [[IsDeletable]]: *false*, [[IsStrict]]: _S_ }. 1. Append _binding_ to _envRec_.[[Bindings]]. 1. Return NormalCompletion(~empty~). @@ -8791,10 +8877,10 @@

InitializeBinding ( _N_, _V_ )

The InitializeBinding concrete method of a declarative Environment Record _envRec_ takes arguments _N_ (a String) and _V_ (an ECMAScript language value). It is used to set the bound value of the current binding of the identifier whose name is the value of the argument _N_ to the value of argument _V_. An uninitialized binding for _N_ must already exist. It performs the following steps when called:

1. Assert: _envRec_.HasBinding(_N_) is *true*. - 1. Let _binding_ be the binding for _N_ in _envRec_.[[Bindings]]. - 1. Assert: _binding_ is uninitialized. - 1. Set the bound value of _binding_ to _V_. - 1. Record that _binding_ has been initialized. + 1. Let _binding_ be the DeclarativeBindingRecord in _envRec_.[[Bindings]] whose [[BoundName]] field equals _N_. + 1. Assert: _binding_.[[IsInitialized]] is *false*. + 1. Set _binding_.[[BoundValue]] to _V_. + 1. Set _binding_.[[IsInitialized]] to *true*. 1. Return NormalCompletion(~empty~). @@ -8808,10 +8894,10 @@

SetMutableBinding ( _N_, _V_, _S_ )

1. Perform _envRec_.CreateMutableBinding(_N_, *true*). 1. Perform _envRec_.InitializeBinding(_N_, _V_). 1. Return NormalCompletion(~empty~). - 1. Let _binding_ be the binding for _N_ in _envRec_.[[Bindings]]. - 1. If _binding_ is a strict binding, set _S_ to *true*. - 1. If _binding_ has not yet been initialized, throw a *ReferenceError* exception. - 1. Else if _binding_ is a mutable binding, change its bound value to _V_. + 1. Let _binding_ be the DeclarativeBindingRecord in _envRec_.[[Bindings]] whose [[BoundName]] field equals _N_. + 1. If _binding_.[[IsStrict]] is *true*, set _S_ to *true*. + 1. If _binding_.[[IsInitialized]] is *false*, throw a *ReferenceError* exception. + 1. Else if _binding_.[[IsMutable]] is *true*, change its bound value to _V_. 1. Else, 1. Assert: This is an attempt to change the value of an immutable binding. 1. If _S_ is *true*, throw a *TypeError* exception. @@ -8828,9 +8914,9 @@

GetBindingValue ( _N_, _S_ )

The GetBindingValue concrete method of a declarative Environment Record _envRec_ takes arguments _N_ (a String) and _S_ (a Boolean). It returns the value of its bound identifier whose name is the value of the argument _N_. If the binding exists but is uninitialized a *ReferenceError* is thrown, regardless of the value of _S_. It performs the following steps when called:

1. Assert: _envRec_.HasBinding(_N_) is *true*. - 1. Let _binding_ be the binding for _N_ in _envRec_.[[Bindings]]. - 1. If _binding_ is an uninitialized binding, throw a *ReferenceError* exception. - 1. Return the value currently bound in _binding_. + 1. Let _binding_ be the DeclarativeBindingRecord in _envRec_.[[Bindings]] whose [[BoundName]] field equals _N_. + 1. If _binding_.[[IsInitialized]] is *false*, throw a *ReferenceError* exception. + 1. Return _binding_.[[BoundValue]]. @@ -8839,8 +8925,8 @@

DeleteBinding ( _N_ )

The DeleteBinding concrete method of a declarative Environment Record _envRec_ takes argument _N_ (a String). It can only delete bindings that have been explicitly designated as being subject to deletion. It performs the following steps when called:

1. Assert: _envRec_.HasBinding(_N_) is *true*. - 1. Let _binding_ be the binding for _N_ in _envRec_.[[Bindings]]. - 1. If _binding_ cannot be deleted, return *false*. + 1. Let _binding_ be the DeclarativeBindingRecord in _envRec_.[[Bindings]] whose [[BoundName]] field equals _N_. + 1. If _binding_.[[IsDeletable]] is *false*, return *false*. 1. Remove _binding_ from _envRec_.[[Bindings]]. 1. Return *true*. @@ -9598,6 +9684,46 @@

Module Environment Records

+

The [[Bindings]] of a Module Environment Record can include ImportDeclarativeBindingRecords. These have all the fields of DeclarativeBindingRecords, plus the additional state fields listed in the following table.

+ + + + + + + + + + + + + + + + + + + +
+ Field Name + + Value + + Meaning +
+ [[TargetModuleRec]] + + a Module Record + + ? +
+ [[TargetName]] + + a String + + the name of a binding that exists in [[TargetModuleRec]]'s module Environment Record. +
+

The behaviour of the additional concrete specification methods for module Environment Records are defined by the following algorithms:

@@ -9606,14 +9732,15 @@

GetBindingValue ( _N_, _S_ )

1. Assert: _S_ is *true*. 1. Assert: _envRec_.HasBinding(_N_) is *true*. - 1. Let _binding_ be the binding for _N_ in _envRec_.[[Bindings]]. - 1. If _binding_ is an indirect binding, then - 1. Let _M_ and _N2_ be the indirection values provided when this binding for _N_ was created. + 1. Let _binding_ be the DeclarativeBindingRecord in _envRec_.[[Bindings]] whose [[BoundName]] field equals _N_. + 1. If _binding_ is an ImportDeclarativeBindingRecord, then + 1. Let _M_ be _binding_.[[TargetModuleRec]]. + 1. Let _N2_ be _binding_.[[TargetName]]. 1. Let _targetEnv_ be _M_.[[Environment]]. 1. If _targetEnv_ is *undefined*, throw a *ReferenceError* exception. 1. Return ? _targetEnv_.GetBindingValue(_N2_, *true*). - 1. If _binding_ is an uninitialized binding, throw a *ReferenceError* exception. - 1. Return the value currently bound in _binding_. + 1. If _binding_.[[IsInitialized]] is *false*, throw a *ReferenceError* exception. + 1. Return _binding_.[[BoundValue]].

_S_ will always be *true* because a |Module| is always strict mode code.

@@ -9654,7 +9781,7 @@

CreateImportBinding ( _N_, _M_, _N2_ )

1. Assert: _envRec_.HasBinding(_N_) is *false*. 1. Assert: _M_ is a Module Record. 1. Assert: When _M_.[[Environment]] is instantiated it will have a direct binding for _N2_. - 1. Let _binding_ be an immutable indirect binding for _N_ that references _M_ and _N2_ as its target binding and record that the binding is initialized. + 1. Let _binding_ be ImportDeclarativeBindingRecord { [[BoundName]]: _N_, [[IsInitialized]]: *true*, [[BoundValue]]: *undefined*, [[IsMutable]]: *false*, [[IsDeletable]]: *false*, [[IsStrict]]: *false*, [[TargetModuleRec]]: _M_, [[TargetName]]: _N2_ }. 1. Append _binding_ to _envRec_.[[Bindings]]. 1. Return NormalCompletion(~empty~). @@ -42908,8 +43035,8 @@

Changes to BlockDeclarationInstantiation

During BlockDeclarationInstantiation the following steps are performed in place of step :

- 1. Let _binding_ be the binding for _fn_ in _env_.[[Bindings]]. - 1. If _binding_ is an uninitialized binding, then + 1. Let _binding_ be the DeclarativeBindingRecord in _env_.[[Bindings]] whose [[BoundName]] field equals _fn_. + 1. If _binding_.[[IsInitialized]] is *false*, then 1. Perform _env_.InitializeBinding(_fn_, _fo_). 1. Else, 1. Assert: _d_ is a |FunctionDeclaration|.