blob: dff48b33a976451d2300f74afe1097c025cacdc1 [file] [log] [blame]
// Copyright 2023 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
namespace collections {
// https://tc39.es/proposal-set-methods/#sec-set.prototype.issupersetof
@incrementUseCounter('v8::Isolate::kSetMethods')
transitioning javascript builtin SetPrototypeIsSupersetOf(
js-implicit context: NativeContext, receiver: JSAny)(
other: JSAny): Boolean {
const methodName: constexpr string = 'Set.prototype.isSupersetOf';
const fastIteratorResultMap = GetIteratorResultMap();
// 1. Let O be the this value.
// 2. Perform ? RequireInternalSlot(O, [[SetData]]).
const o = Cast<JSSet>(receiver) otherwise
ThrowTypeError(
MessageTemplate::kIncompatibleMethodReceiver, methodName, receiver);
// 3. Let otherRec be ? GetSetRecord(other).
let otherRec = GetSetRecord(other, methodName);
let table = NewStableBackingTableWitness(o);
// 4. Let thisSize be the number of elements in O.[[SetData]].
const thisSize = table.LoadSize();
// 5. If thisSize < otherRec.[[Size]], return false.
if (Convert<Number>(thisSize) < otherRec.size) {
return False;
}
try {
typeswitch (other) {
case (otherSet: JSSetWithNoCustomIteration): {
CheckSetRecordHasJSSetMethods(otherRec) otherwise SlowPath;
const otherTable = NewStableBackingTableWitness(otherSet);
let iter = collections::NewUnmodifiedOrderedHashSetIterator(
otherTable.GetTable());
while (true) {
const nextValue = iter.Next() otherwise Done;
if (!table.HasKey(nextValue)) {
return False;
}
}
}
case (otherMap: JSMapWithNoCustomIteration): {
CheckSetRecordHasJSMapMethods(otherRec) otherwise SlowPath;
const otherTable = NewStableBackingTableWitness(otherMap);
let iter = collections::NewUnmodifiedOrderedHashMapIterator(
otherTable.GetTable());
while (true) {
const nextValue = iter.Next() otherwise Done;
if (!table.HasKey(nextValue.key)) {
return False;
}
}
}
case (JSAny): {
goto SlowPath;
}
}
} label SlowPath {
// 6. Let keysIter be ? GetKeysIterator(otherRec).
let keysIter =
GetKeysIterator(otherRec.object, UnsafeCast<Callable>(otherRec.keys));
// 7. Let next be true.
let nextRecord: JSReceiver;
// 8. Repeat, while next is not false,
while (true) {
// a. Set next to ? IteratorStep(keysIter).
nextRecord = iterator::IteratorStep(keysIter, fastIteratorResultMap)
otherwise Done;
// b. If next is not false, then
// i. Let nextValue be ? IteratorValue(next).
const nextValue =
iterator::IteratorValue(nextRecord, fastIteratorResultMap);
// ii. If SetDataHas(O.[[SetData]], nextValue) is false, then
table.ReloadTable();
if (!table.HasKey(nextValue)) {
// 1. Perform ? IteratorClose(keysIter,
// NormalCompletion(unused)).
// 2. Return false.
iterator::IteratorClose(keysIter);
return False;
}
}
} label Done {
// 9. Return true.
return True;
}
unreachable;
}
}