Skip to content

Commit a78d504

Browse files
bakkotljharb
authored andcommitted
Normative: add set methods (#3306)
- suggested changes (to the set-methods PR) (#3308)
1 parent 30257dd commit a78d504

File tree

1 file changed

+343
-4
lines changed

1 file changed

+343
-4
lines changed

spec.html

Lines changed: 343 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -42020,6 +42020,152 @@ <h1>Set Objects</h1>
4202042020
<p>Set objects are collections of ECMAScript language values. A distinct value may only occur once as an element of a Set's collection. Distinct values are discriminated using the SameValueZero comparison algorithm.</p>
4202142021
<p>Set objects must be implemented using either hash tables or other mechanisms that, on average, provide access times that are sublinear on the number of elements in the collection. The data structure used in this specification is only intended to describe the required observable semantics of Set objects. It is not intended to be a viable implementation model.</p>
4202242022

42023+
<emu-clause id="sec-abstract-operations-for-set-objects">
42024+
<h1>Abstract Operations For Set Objects</h1>
42025+
42026+
<emu-clause id="sec-set-records">
42027+
<h1>Set Records</h1>
42028+
<p>An <dfn variants="Set Records">Set Record</dfn> is a Record value used to encapsulate the interface of a Set or similar object.</p>
42029+
<p>Set Records have the fields listed in <emu-xref href="#table-set-record-fields"></emu-xref>.</p>
42030+
<emu-table id="table-set-record-fields" caption="Set Record Fields">
42031+
<table>
42032+
<tr>
42033+
<th>
42034+
Field Name
42035+
</th>
42036+
<th>
42037+
Value
42038+
</th>
42039+
<th>
42040+
Meaning
42041+
</th>
42042+
</tr>
42043+
<tr>
42044+
<td>
42045+
[[SetObject]]
42046+
</td>
42047+
<td>
42048+
an Object
42049+
</td>
42050+
<td>
42051+
the Set or similar object.
42052+
</td>
42053+
</tr>
42054+
<tr>
42055+
<td>
42056+
[[Size]]
42057+
</td>
42058+
<td>
42059+
a non-negative integer or +∞
42060+
</td>
42061+
<td>
42062+
The reported size of the object.
42063+
</td>
42064+
</tr>
42065+
<tr>
42066+
<td>
42067+
[[Has]]
42068+
</td>
42069+
<td>
42070+
a function object
42071+
</td>
42072+
<td>
42073+
The `has` method of the object.
42074+
</td>
42075+
</tr>
42076+
<tr>
42077+
<td>
42078+
[[Keys]]
42079+
</td>
42080+
<td>
42081+
a function object
42082+
</td>
42083+
<td>
42084+
The `keys` method of the object.
42085+
</td>
42086+
</tr>
42087+
</table>
42088+
</emu-table>
42089+
</emu-clause>
42090+
42091+
<emu-clause id="sec-getsetrecord" type="abstract operation">
42092+
<h1>
42093+
GetSetRecord (
42094+
_obj_: an ECMAScript language value,
42095+
): either a normal completion containing a Set Record or a throw completion
42096+
</h1>
42097+
<dl class="header">
42098+
</dl>
42099+
<emu-alg>
42100+
1. If _obj_ is not an Object, throw a *TypeError* exception.
42101+
1. Let _rawSize_ be ? Get(_obj_, *"size"*).
42102+
1. Let _numSize_ be ? ToNumber(_rawSize_).
42103+
1. NOTE: If _rawSize_ is *undefined*, then _numSize_ will be *NaN*.
42104+
1. If _numSize_ is *NaN*, throw a *TypeError* exception.
42105+
1. Let _intSize_ be ! ToIntegerOrInfinity(_numSize_).
42106+
1. If _intSize_ &lt; 0, throw a *RangeError* exception.
42107+
1. Let _has_ be ? Get(_obj_, *"has"*).
42108+
1. If IsCallable(_has_) is *false*, throw a *TypeError* exception.
42109+
1. Let _keys_ be ? Get(_obj_, *"keys"*).
42110+
1. If IsCallable(_keys_) is *false*, throw a *TypeError* exception.
42111+
1. Return a new Set Record { [[SetObject]]: _obj_, [[Size]]: _intSize_, [[Has]]: _has_, [[Keys]]: _keys_ }.
42112+
</emu-alg>
42113+
</emu-clause>
42114+
42115+
<emu-clause id="sec-setdatahas" type="abstract operation">
42116+
<h1>
42117+
SetDataHas (
42118+
_setData_: a List of either ECMAScript language values or ~empty~,
42119+
_value_: an ECMAScript language value,
42120+
): a Boolean
42121+
</h1>
42122+
<dl class="header">
42123+
</dl>
42124+
<emu-alg>
42125+
1. If SetDataIndex(_setData_, _value_) is ~not-found~, return *false*.
42126+
1. Return *true*.
42127+
</emu-alg>
42128+
</emu-clause>
42129+
42130+
<emu-clause id="sec-setdataindex" type="abstract operation">
42131+
<h1>
42132+
SetDataIndex (
42133+
_setData_: a List of either ECMAScript language values or ~empty~,
42134+
_value_: an ECMAScript language value,
42135+
): a non-negative integer or ~not-found~
42136+
</h1>
42137+
<dl class="header">
42138+
</dl>
42139+
<emu-alg>
42140+
1. Set _value_ to CanonicalizeKeyedCollectionKey(_value_).
42141+
1. Let _size_ be the number of elements in _setData_.
42142+
1. Let _index_ be 0.
42143+
1. Repeat, while _index_ &lt; _size_,
42144+
1. Let _e_ be _setData_[_index_].
42145+
1. If _e_ is not ~empty~ and _e_ is _value_, then
42146+
1. Return _index_.
42147+
1. Set _index_ to _index_ + 1.
42148+
1. Return ~not-found~.
42149+
</emu-alg>
42150+
</emu-clause>
42151+
42152+
<emu-clause id="sec-setdatasize" type="abstract operation">
42153+
<h1>
42154+
SetDataSize (
42155+
_setData_: a List of either ECMAScript language values or ~empty~,
42156+
): a non-negative integer
42157+
</h1>
42158+
<dl class="header">
42159+
</dl>
42160+
<emu-alg>
42161+
1. Let _count_ be 0.
42162+
1. For each element _e_ of _setData_, do
42163+
1. If _e_ is not ~empty~, set _count_ to _count_ + 1.
42164+
1. Return _count_.
42165+
</emu-alg>
42166+
</emu-clause>
42167+
</emu-clause>
42168+
4202342169
<emu-clause id="sec-set-constructor">
4202442170
<h1>The Set Constructor</h1>
4202542171
<p>The Set constructor:</p>
@@ -42141,6 +42287,40 @@ <h1>Set.prototype.delete ( _value_ )</h1>
4214142287
</emu-note>
4214242288
</emu-clause>
4214342289

42290+
<emu-clause id="sec-set.prototype.difference">
42291+
<h1>Set.prototype.difference ( _other_ )</h1>
42292+
<p>This method performs the following steps when called:</p>
42293+
<emu-alg>
42294+
1. Let _O_ be the *this* value.
42295+
1. Perform ? RequireInternalSlot(_O_, [[SetData]]).
42296+
1. Let _otherRec_ be ? GetSetRecord(_other_).
42297+
1. Let _resultSetData_ be a copy of _O_.[[SetData]].
42298+
1. If SetDataSize(_O_.[[SetData]]) ≤ _otherRec_.[[Size]], then
42299+
1. Let _thisSize_ be the number of elements in _O_.[[SetData]].
42300+
1. Let _index_ be 0.
42301+
1. Repeat, while _index_ &lt; _thisSize_,
42302+
1. Let _e_ be _resultSetData_[_index_].
42303+
1. If _e_ is not ~empty~, then
42304+
1. Let _inOther_ be ToBoolean(? Call(_otherRec_.[[Has]], _otherRec_.[[SetObject]], « _e_ »)).
42305+
1. If _inOther_ is *true*, then
42306+
1. Set _resultSetData_[_index_] to ~empty~.
42307+
1. Set _index_ to _index_ + 1.
42308+
1. Else,
42309+
1. Let _keysIter_ be ? GetIteratorFromMethod(_otherRec_.[[SetObject]], _otherRec_.[[Keys]]).
42310+
1. Let _next_ be ~not-started~.
42311+
1. Repeat, while _next_ is not ~done~,
42312+
1. Set _next_ to ? IteratorStepValue(_keysIter_).
42313+
1. If _next_ is not ~done~, then
42314+
1. Set _next_ to CanonicalizeKeyedCollectionKey(_next_).
42315+
1. Let _valueIndex_ be SetDataIndex(_resultSetData_, _next_).
42316+
1. If _valueIndex_ is not ~not-found~, then
42317+
1. Set _resultSetData_[_valueIndex_] to ~empty~.
42318+
1. Let _result_ be OrdinaryObjectCreate(%Set.prototype%, « [[SetData]] »).
42319+
1. Set _result_.[[SetData]] to _resultSetData_.
42320+
1. Return _result_.
42321+
</emu-alg>
42322+
</emu-clause>
42323+
4214442324
<emu-clause id="sec-set.prototype.entries">
4214542325
<h1>Set.prototype.entries ( )</h1>
4214642326
<p>This method performs the following steps when called:</p>
@@ -42195,6 +42375,119 @@ <h1>Set.prototype.has ( _value_ )</h1>
4219542375
</emu-alg>
4219642376
</emu-clause>
4219742377

42378+
<emu-clause id="sec-set.prototype.intersection">
42379+
<h1>Set.prototype.intersection ( _other_ )</h1>
42380+
<p>This method performs the following steps when called:</p>
42381+
<emu-alg>
42382+
1. Let _O_ be the *this* value.
42383+
1. Perform ? RequireInternalSlot(_O_, [[SetData]]).
42384+
1. Let _otherRec_ be ? GetSetRecord(_other_).
42385+
1. Let _resultSetData_ be a new empty List.
42386+
1. If SetDataSize(_O_.[[SetData]]) ≤ _otherRec_.[[Size]], then
42387+
1. Let _thisSize_ be the number of elements in _O_.[[SetData]].
42388+
1. Let _index_ be 0.
42389+
1. Repeat, while _index_ &lt; _thisSize_,
42390+
1. Let _e_ be _O_.[[SetData]][_index_].
42391+
1. Set _index_ to _index_ + 1.
42392+
1. If _e_ is not ~empty~, then
42393+
1. Let _inOther_ be ToBoolean(? Call(_otherRec_.[[Has]], _otherRec_.[[SetObject]], « _e_ »)).
42394+
1. If _inOther_ is *true*, then
42395+
1. NOTE: It is possible for earlier calls to _otherRec_.[[Has]] to remove and re-add an element of _O_.[[SetData]], which can cause the same element to be visited twice during this iteration.
42396+
1. If SetDataHas(_resultSetData_, _e_) is *false*, then
42397+
1. Append _e_ to _resultSetData_.
42398+
1. NOTE: The number of elements in _O_.[[SetData]] may have increased during execution of _otherRec_.[[Has]].
42399+
1. Set _thisSize_ to the number of elements in _O_.[[SetData]].
42400+
1. Else,
42401+
1. Let _keysIter_ be ? GetIteratorFromMethod(_otherRec_.[[SetObject]], _otherRec_.[[Keys]]).
42402+
1. Let _next_ be ~not-started~.
42403+
1. Repeat, while _next_ is not ~done~,
42404+
1. Set _next_ to ? IteratorStepValue(_keysIter_).
42405+
1. If _next_ is not ~done~, then
42406+
1. Set _next_ to CanonicalizeKeyedCollectionKey(_next_).
42407+
1. Let _inThis_ be SetDataHas(_O_.[[SetData]], _next_).
42408+
1. If _inThis_ is *true*, then
42409+
1. NOTE: Because _other_ is an arbitrary object, it is possible for its *"keys"* iterator to produce the same value more than once.
42410+
1. If SetDataHas(_resultSetData_, _next_) is *false*, then
42411+
1. Append _next_ to _resultSetData_.
42412+
1. Let _result_ be OrdinaryObjectCreate(%Set.prototype%, « [[SetData]] »).
42413+
1. Set _result_.[[SetData]] to _resultSetData_.
42414+
1. Return _result_.
42415+
</emu-alg>
42416+
</emu-clause>
42417+
42418+
<emu-clause id="sec-set.prototype.isdisjointfrom">
42419+
<h1>Set.prototype.isDisjointFrom ( _other_ )</h1>
42420+
<p>This method performs the following steps when called:</p>
42421+
<emu-alg>
42422+
1. Let _O_ be the *this* value.
42423+
1. Perform ? RequireInternalSlot(_O_, [[SetData]]).
42424+
1. Let _otherRec_ be ? GetSetRecord(_other_).
42425+
1. If SetDataSize(_O_.[[SetData]]) ≤ _otherRec_.[[Size]], then
42426+
1. Let _thisSize_ be the number of elements in _O_.[[SetData]].
42427+
1. Let _index_ be 0.
42428+
1. Repeat, while _index_ &lt; _thisSize_,
42429+
1. Let _e_ be _O_.[[SetData]][_index_].
42430+
1. Set _index_ to _index_ + 1.
42431+
1. If _e_ is not ~empty~, then
42432+
1. Let _inOther_ be ToBoolean(? Call(_otherRec_.[[Has]], _otherRec_.[[SetObject]], « _e_ »)).
42433+
1. If _inOther_ is *true*, return *false*.
42434+
1. NOTE: The number of elements in _O_.[[SetData]] may have increased during execution of _otherRec_.[[Has]].
42435+
1. Set _thisSize_ to the number of elements in _O_.[[SetData]].
42436+
1. Else,
42437+
1. Let _keysIter_ be ? GetIteratorFromMethod(_otherRec_.[[SetObject]], _otherRec_.[[Keys]]).
42438+
1. Let _next_ be ~not-started~.
42439+
1. Repeat, while _next_ is not ~done~,
42440+
1. Set _next_ to ? IteratorStepValue(_keysIter_).
42441+
1. If _next_ is not ~done~, then
42442+
1. If SetDataHas(_O_.[[SetData]], _next_) is *true*, then
42443+
1. Perform ? IteratorClose(_keysIter_, NormalCompletion(~unused~)).
42444+
1. Return *false*.
42445+
1. Return *true*.
42446+
</emu-alg>
42447+
</emu-clause>
42448+
42449+
<emu-clause id="sec-set.prototype.issubsetof">
42450+
<h1>Set.prototype.isSubsetOf ( _other_ )</h1>
42451+
<p>This method performs the following steps when called:</p>
42452+
<emu-alg>
42453+
1. Let _O_ be the *this* value.
42454+
1. Perform ? RequireInternalSlot(_O_, [[SetData]]).
42455+
1. Let _otherRec_ be ? GetSetRecord(_other_).
42456+
1. If SetDataSize(_O_.[[SetData]]) > _otherRec_.[[Size]], return *false*.
42457+
1. Let _thisSize_ be the number of elements in _O_.[[SetData]].
42458+
1. Let _index_ be 0.
42459+
1. Repeat, while _index_ &lt; _thisSize_,
42460+
1. Let _e_ be _O_.[[SetData]][_index_].
42461+
1. Set _index_ to _index_ + 1.
42462+
1. If _e_ is not ~empty~, then
42463+
1. Let _inOther_ be ToBoolean(? Call(_otherRec_.[[Has]], _otherRec_.[[SetObject]], « _e_ »)).
42464+
1. If _inOther_ is *false*, return *false*.
42465+
1. NOTE: The number of elements in _O_.[[SetData]] may have increased during execution of _otherRec_.[[Has]].
42466+
1. Set _thisSize_ to the number of elements in _O_.[[SetData]].
42467+
1. Return *true*.
42468+
</emu-alg>
42469+
</emu-clause>
42470+
42471+
<emu-clause id="sec-set.prototype.issupersetof">
42472+
<h1>Set.prototype.isSupersetOf ( _other_ )</h1>
42473+
<p>This method performs the following steps when called:</p>
42474+
<emu-alg>
42475+
1. Let _O_ be the *this* value.
42476+
1. Perform ? RequireInternalSlot(_O_, [[SetData]]).
42477+
1. Let _otherRec_ be ? GetSetRecord(_other_).
42478+
1. If SetDataSize(_O_.[[SetData]]) &lt; _otherRec_.[[Size]], return *false*.
42479+
1. Let _keysIter_ be ? GetIteratorFromMethod(_otherRec_.[[SetObject]], _otherRec_.[[Keys]]).
42480+
1. Let _next_ be ~not-started~.
42481+
1. Repeat, while _next_ is not ~done~,
42482+
1. Set _next_ to ? IteratorStepValue(_keysIter_).
42483+
1. If _next_ is not ~done~, then
42484+
1. If SetDataHas(_O_.[[SetData]], _next_) is *false*, then
42485+
1. Perform ? IteratorClose(_keysIter_, NormalCompletion(~unused~)).
42486+
1. Return *false*.
42487+
1. Return *true*.
42488+
</emu-alg>
42489+
</emu-clause>
42490+
4219842491
<emu-clause id="sec-set.prototype.keys">
4219942492
<h1>Set.prototype.keys ( )</h1>
4220042493
<p>The initial value of the *"keys"* property is %Set.prototype.values%, defined in <emu-xref href="#sec-set.prototype.values"></emu-xref>.</p>
@@ -42209,10 +42502,56 @@ <h1>get Set.prototype.size</h1>
4220942502
<emu-alg>
4221042503
1. Let _S_ be the *this* value.
4221142504
1. Perform ? RequireInternalSlot(_S_, [[SetData]]).
42212-
1. Let _count_ be 0.
42213-
1. For each element _e_ of _S_.[[SetData]], do
42214-
1. If _e_ is not ~empty~, set _count_ to _count_ + 1.
42215-
1. Return 𝔽(_count_).
42505+
1. Let _size_ be SetDataSize(_S_.[[SetData]]).
42506+
1. Return 𝔽(_size_).
42507+
</emu-alg>
42508+
</emu-clause>
42509+
42510+
<emu-clause id="sec-set.prototype.symmetricdifference">
42511+
<h1>Set.prototype.symmetricDifference ( _other_ )</h1>
42512+
<p>This method performs the following steps when called:</p>
42513+
<emu-alg>
42514+
1. Let _O_ be the *this* value.
42515+
1. Perform ? RequireInternalSlot(_O_, [[SetData]]).
42516+
1. Let _otherRec_ be ? GetSetRecord(_other_).
42517+
1. Let _keysIter_ be ? GetIteratorFromMethod(_otherRec_.[[SetObject]], _otherRec_.[[Keys]]).
42518+
1. Let _resultSetData_ be a copy of _O_.[[SetData]].
42519+
1. Let _next_ be ~not-started~.
42520+
1. Repeat, while _next_ is not ~done~,
42521+
1. Set _next_ to ? IteratorStepValue(_keysIter_).
42522+
1. If _next_ is not ~done~, then
42523+
1. Set _next_ to CanonicalizeKeyedCollectionKey(_next_).
42524+
1. Let _resultIndex_ be SetDataIndex(_resultSetData_, _next_).
42525+
1. If _resultIndex_ is ~not-found~, let _alreadyInResult_ be *false*. Otherwise let _alreadyInResult_ be *true*.
42526+
1. If SetDataHas(_O_.[[SetData]], _next_) is *true*, then
42527+
1. If _alreadyInResult_ is *true*, set _resultSetData_[_resultIndex_] to ~empty~.
42528+
1. Else,
42529+
1. If _alreadyInResult_ is *false*, append _next_ to _resultSetData_.
42530+
1. Let _result_ be OrdinaryObjectCreate(%Set.prototype%, « [[SetData]] »).
42531+
1. Set _result_.[[SetData]] to _resultSetData_.
42532+
1. Return _result_.
42533+
</emu-alg>
42534+
</emu-clause>
42535+
42536+
<emu-clause id="sec-set.prototype.union">
42537+
<h1>Set.prototype.union ( _other_ )</h1>
42538+
<p>This method performs the following steps when called:</p>
42539+
<emu-alg>
42540+
1. Let _O_ be the *this* value.
42541+
1. Perform ? RequireInternalSlot(_O_, [[SetData]]).
42542+
1. Let _otherRec_ be ? GetSetRecord(_other_).
42543+
1. Let _keysIter_ be ? GetIteratorFromMethod(_otherRec_.[[SetObject]], _otherRec_.[[Keys]]).
42544+
1. Let _resultSetData_ be a copy of _O_.[[SetData]].
42545+
1. Let _next_ be ~not-started~.
42546+
1. Repeat, while _next_ is not ~done~,
42547+
1. Set _next_ to ? IteratorStepValue(_keysIter_).
42548+
1. If _next_ is not ~done~, then
42549+
1. Set _next_ to CanonicalizeKeyedCollectionKey(_next_).
42550+
1. If SetDataHas(_resultSetData_, _next_) is *false*, then
42551+
1. Append _next_ to _resultSetData_.
42552+
1. Let _result_ be OrdinaryObjectCreate(%Set.prototype%, « [[SetData]] »).
42553+
1. Set _result_.[[SetData]] to _resultSetData_.
42554+
1. Return _result_.
4221642555
</emu-alg>
4221742556
</emu-clause>
4221842557

0 commit comments

Comments
 (0)