mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2024-11-26 01:20:25 +00:00
LibJS: Implement Set.prototype.difference
This commit is contained in:
parent
9e693304ff
commit
be8329d5f6
Notes:
sideshowbarker
2024-07-17 05:13:53 +09:00
Author: https://github.com/IdanHo Commit: https://github.com/SerenityOS/serenity/commit/be8329d5f6 Pull-request: https://github.com/SerenityOS/serenity/pull/16279 Reviewed-by: https://github.com/TobyAsE Reviewed-by: https://github.com/davidot ✅ Reviewed-by: https://github.com/linusg ✅
4 changed files with 84 additions and 0 deletions
|
@ -148,6 +148,7 @@ namespace JS {
|
|||
P(deleteProperty) \
|
||||
P(deref) \
|
||||
P(description) \
|
||||
P(difference) \
|
||||
P(direction) \
|
||||
P(disambiguation) \
|
||||
P(done) \
|
||||
|
|
|
@ -34,6 +34,7 @@ void SetPrototype::initialize(Realm& realm)
|
|||
define_native_function(realm, vm.names.values, values, 0, attr);
|
||||
define_native_function(realm, vm.names.union_, union_, 1, attr);
|
||||
define_native_function(realm, vm.names.intersection, intersection, 1, attr);
|
||||
define_native_function(realm, vm.names.difference, difference, 1, attr);
|
||||
define_native_accessor(realm, vm.names.size, size_getter, {}, Attribute::Configurable);
|
||||
|
||||
define_direct_property(vm.names.keys, get_without_side_effects(vm.names.values), attr);
|
||||
|
@ -313,4 +314,73 @@ JS_DEFINE_NATIVE_FUNCTION(SetPrototype::intersection)
|
|||
return result;
|
||||
}
|
||||
|
||||
// 3 Set.prototype.difference ( other ), https://tc39.es/proposal-set-methods/#sec-set.prototype.difference
|
||||
JS_DEFINE_NATIVE_FUNCTION(SetPrototype::difference)
|
||||
{
|
||||
// 1. Let O be the this value.
|
||||
// 2. Perform ? RequireInternalSlot(O, [[SetData]]).
|
||||
auto* set = TRY(typed_this_object(vm));
|
||||
|
||||
// 3. Let otherRec be ? GetSetRecord(other).
|
||||
auto other_record = TRY(get_set_record(vm, vm.argument(0)));
|
||||
|
||||
// 4. Let resultSetData be a copy of O.[[SetData]].
|
||||
auto result = set->copy();
|
||||
|
||||
// 5. Let thisSize be the number of elements in O.[[SetData]].
|
||||
auto this_size = set->set_size();
|
||||
|
||||
// 6. If thisSize ≤ otherRec.[[Size]], then
|
||||
if (this_size <= other_record.size) {
|
||||
// a. For each element e of resultSetData, do
|
||||
for (auto& element : *set) {
|
||||
// i. If e is not empty, then
|
||||
// 1. Let inOther be ToBoolean(? Call(otherRec.[[Has]], otherRec.[[Set]], « e »)).
|
||||
auto in_other = TRY(call(vm, *other_record.has, other_record.set, element.key)).to_boolean();
|
||||
// 2. If inOther is true, then
|
||||
if (in_other) {
|
||||
// a. Remove e from resultSetData.
|
||||
result->set_remove(element.key);
|
||||
}
|
||||
}
|
||||
}
|
||||
// 7. Else,
|
||||
else {
|
||||
// a. Let keysIter be ? GetKeysIterator(otherRec).
|
||||
auto keys_iterator = TRY(get_keys_iterator(vm, other_record));
|
||||
|
||||
// b. Let next be true.
|
||||
auto next = true;
|
||||
|
||||
// c. Repeat, while next is not false,
|
||||
while (next) {
|
||||
// i. Set next to ? IteratorStep(keysIter).
|
||||
auto* iterator_result = TRY(iterator_step(vm, keys_iterator));
|
||||
next = iterator_result;
|
||||
|
||||
// ii. If next is not false, then
|
||||
if (next) {
|
||||
// 1. Let nextValue be ? IteratorValue(next).
|
||||
auto next_value = TRY(iterator_value(vm, *iterator_result));
|
||||
|
||||
// 2. If nextValue is -0𝔽, set nextValue to +0𝔽.
|
||||
if (next_value.is_negative_zero())
|
||||
next_value = Value(0);
|
||||
|
||||
// 3. If SetDataHas(resultSetData, nextValue) is true, then
|
||||
if (result->set_has(next_value)) {
|
||||
// a. Remove nextValue from resultSetData.
|
||||
result->set_remove(next_value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 8. Let result be OrdinaryObjectCreate(%Set.prototype%, « [[SetData]] »).
|
||||
// 9. Set result.[[SetData]] to resultSetData.
|
||||
|
||||
// 10. Return result.
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -30,6 +30,7 @@ private:
|
|||
JS_DECLARE_NATIVE_FUNCTION(values);
|
||||
JS_DECLARE_NATIVE_FUNCTION(union_);
|
||||
JS_DECLARE_NATIVE_FUNCTION(intersection);
|
||||
JS_DECLARE_NATIVE_FUNCTION(difference);
|
||||
|
||||
JS_DECLARE_NATIVE_FUNCTION(size_getter);
|
||||
};
|
||||
|
|
|
@ -0,0 +1,12 @@
|
|||
test("basic functionality", () => {
|
||||
expect(Set.prototype.difference).toHaveLength(1);
|
||||
|
||||
const set1 = new Set(["a", "b", "c"]);
|
||||
const set2 = new Set(["b", "c", "d", "e"]);
|
||||
const difference1to2 = set1.difference(set2);
|
||||
expect(difference1to2).toHaveSize(1);
|
||||
expect(difference1to2.has("a")).toBeTrue();
|
||||
const difference2to1 = set2.difference(set1);
|
||||
expect(difference2to1).toHaveSize(2);
|
||||
["d", "e"].forEach(value => expect(difference2to1.has(value)).toBeTrue());
|
||||
});
|
Loading…
Reference in a new issue