In CreateGlobalVarBinding (§9.1.1.4.16), step 5 reads:
| Step |
Operation |
| 5a |
objectRecord.CreateMutableBinding(name, deletable) |
| 5b |
objectRecord.InitializeBinding(name, undefined) |
However, CreateMutableBinding for an Object Environment Record (§9.1.1.2.2) already calls DefinePropertyOrThrow with [[Value]]: undefined, which both creates and initializes the property. Step 5b therefore performs a redundant [[Set]] on a property already set to undefined.
The description of CreateGlobalVarBinding states: "It creates and initializes a mutable binding" — yet the current steps perform initialization twice.
Impact
| Global object type |
Effect of step 5b |
| Ordinary object |
No observable effect — redundant no-op |
| Proxy object (permitted by §9.3.1 step 10) |
Unintended [[Set]] trap invocation after [[DefineOwnProperty]] — observable side effect not implied by the operation's stated semantics |
The spec explicitly acknowledges in §16.1.7 Note 2 that a Proxy global object is a valid and known scenario:
"if the global object is defined using Proxy exotic objects then the runtime tests for conflicting declarations may be unreliable resulting in an abrupt completion and some global declarations not being instantiated."
This makes the unintended [[Set]] in step 5b a concrete risk, not a theoretical one.
By contrast, the sibling operation CreateGlobalFunctionBinding (§9.1.1.4.17) performs the same DefinePropertyOrThrow + Set pattern and explicitly documents it in a NOTE:
"Step 7 is equivalent to what calling the InitializeBinding concrete method would do and if globalObject is a Proxy will produce the same sequence of Proxy trap calls."
This NOTE is absent in CreateGlobalVarBinding, leaving it ambiguous whether the [[Set]] in step 5b is intentional or an oversight.
Possible resolutions
- Remove step 5b —
CreateMutableBinding already fulfills the "creates and initializes" contract.
- Replace steps 5a–5b with a single
DefinePropertyOrThrow call, making the intent explicit and eliminating the extra trap invocation for Proxy objects.
- Add a NOTE analogous to §9.1.1.4.17 clarifying that step 5b intentionally triggers
[[Set]] for Proxy global objects — if this behaviour is by design.
In
CreateGlobalVarBinding(§9.1.1.4.16), step 5 reads:objectRecord.CreateMutableBinding(name, deletable)objectRecord.InitializeBinding(name, undefined)However,
CreateMutableBindingfor an Object Environment Record (§9.1.1.2.2) already callsDefinePropertyOrThrowwith[[Value]]: undefined, which both creates and initializes the property. Step 5b therefore performs a redundant[[Set]]on a property already set toundefined.The description of
CreateGlobalVarBindingstates: "It creates and initializes a mutable binding" — yet the current steps perform initialization twice.Impact
[[Set]]trap invocation after[[DefineOwnProperty]]— observable side effect not implied by the operation's stated semanticsThe spec explicitly acknowledges in §16.1.7 Note 2 that a Proxy global object is a valid and known scenario:
This makes the unintended
[[Set]]in step 5b a concrete risk, not a theoretical one.By contrast, the sibling operation
CreateGlobalFunctionBinding(§9.1.1.4.17) performs the sameDefinePropertyOrThrow+Setpattern and explicitly documents it in a NOTE:This NOTE is absent in
CreateGlobalVarBinding, leaving it ambiguous whether the[[Set]]in step 5b is intentional or an oversight.Possible resolutions
CreateMutableBindingalready fulfills the "creates and initializes" contract.DefinePropertyOrThrowcall, making the intent explicit and eliminating the extra trap invocation for Proxy objects.[[Set]]for Proxy global objects — if this behaviour is by design.