瀏覽代碼

LibJS: Implement Set.prototype.isSubsetOf

Idan Horowitz 2 年之前
父節點
當前提交
e29be4eaa8

+ 1 - 0
Userland/Libraries/LibJS/Runtime/CommonPropertyNames.h

@@ -300,6 +300,7 @@ namespace JS {
     P(isPrototypeOf)                         \
     P(isSafeInteger)                         \
     P(isSealed)                              \
+    P(isSubsetOf)                            \
     P(isView)                                \
     P(isoDay)                                \
     P(isoHour)                               \

+ 32 - 0
Userland/Libraries/LibJS/Runtime/SetPrototype.cpp

@@ -36,6 +36,7 @@ void SetPrototype::initialize(Realm& realm)
     define_native_function(realm, vm.names.intersection, intersection, 1, attr);
     define_native_function(realm, vm.names.difference, difference, 1, attr);
     define_native_function(realm, vm.names.symmetricDifference, symmetric_difference, 1, attr);
+    define_native_function(realm, vm.names.isSubsetOf, is_subset_of, 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);
@@ -439,4 +440,35 @@ JS_DEFINE_NATIVE_FUNCTION(SetPrototype::symmetric_difference)
     return result;
 }
 
+// 5 Set.prototype.isSubsetOf ( other ), https://tc39.es/proposal-set-methods/#sec-set.prototype.issubsetof
+JS_DEFINE_NATIVE_FUNCTION(SetPrototype::is_subset_of)
+{
+    // 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 thisSize be the number of elements in O.[[SetData]].
+    auto this_size = set->set_size();
+
+    // 5. If thisSize > otherRec.[[Size]], return false.
+    if (this_size > other_record.size)
+        return false;
+
+    // 6. For each element e of O.[[SetData]], do
+    for (auto& element : *set) {
+        // a. 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();
+
+        // b. If inOther is false, return false.
+        if (!in_other)
+            return false;
+    }
+
+    // 7. Return true.
+    return true;
+}
+
 }

+ 1 - 0
Userland/Libraries/LibJS/Runtime/SetPrototype.h

@@ -32,6 +32,7 @@ private:
     JS_DECLARE_NATIVE_FUNCTION(intersection);
     JS_DECLARE_NATIVE_FUNCTION(difference);
     JS_DECLARE_NATIVE_FUNCTION(symmetric_difference);
+    JS_DECLARE_NATIVE_FUNCTION(is_subset_of);
 
     JS_DECLARE_NATIVE_FUNCTION(size_getter);
 };

+ 8 - 0
Userland/Libraries/LibJS/Tests/builtins/Set/Set.prototype.isSubsetOf.js

@@ -0,0 +1,8 @@
+test("basic functionality", () => {
+    expect(Set.prototype.isSubsetOf).toHaveLength(1);
+
+    const set1 = new Set(["a", "b", "c"]);
+    const set2 = new Set(["b", "c"]);
+    expect(set1.isSubsetOf(set2)).toBeFalse();
+    expect(set2.isSubsetOf(set1)).toBeTrue();
+});