diff --git a/Userland/Libraries/LibJS/Runtime/WeakSetPrototype.cpp b/Userland/Libraries/LibJS/Runtime/WeakSetPrototype.cpp index 8058621a4d..46bcde5f95 100644 --- a/Userland/Libraries/LibJS/Runtime/WeakSetPrototype.cpp +++ b/Userland/Libraries/LibJS/Runtime/WeakSetPrototype.cpp @@ -18,6 +18,11 @@ void WeakSetPrototype::initialize(GlobalObject& global_object) { auto& vm = this->vm(); Object::initialize(global_object); + u8 attr = Attribute::Writable | Attribute::Configurable; + + define_native_function(vm.names.add, add, 1, attr); + define_native_function(vm.names.delete_, delete_, 1, attr); + define_native_function(vm.names.has, has, 1, attr); define_property(vm.well_known_symbol_to_string_tag(), js_string(global_object.heap(), vm.names.WeakSet), Attribute::Configurable); } @@ -38,4 +43,41 @@ WeakSet* WeakSetPrototype::typed_this(VM& vm, GlobalObject& global_object) return static_cast(this_object); } +JS_DEFINE_NATIVE_FUNCTION(WeakSetPrototype::add) +{ + auto* weak_set = typed_this(vm, global_object); + if (!weak_set) + return {}; + auto value = vm.argument(0); + if (!value.is_object()) { + vm.throw_exception(global_object, ErrorType::NotAnObject, value.to_string_without_side_effects()); + return {}; + } + weak_set->values().set(&value.as_object(), AK::HashSetExistingEntryBehavior::Keep); + return weak_set; +} + +JS_DEFINE_NATIVE_FUNCTION(WeakSetPrototype::delete_) +{ + auto* weak_set = typed_this(vm, global_object); + if (!weak_set) + return {}; + auto value = vm.argument(0); + if (!value.is_object()) + return Value(false); + return Value(weak_set->values().remove(&value.as_object())); +} + +JS_DEFINE_NATIVE_FUNCTION(WeakSetPrototype::has) +{ + auto* weak_set = typed_this(vm, global_object); + if (!weak_set) + return {}; + auto value = vm.argument(0); + if (!value.is_object()) + return Value(false); + auto& values = weak_set->values(); + return Value(values.find(&value.as_object()) != values.end()); +} + } diff --git a/Userland/Libraries/LibJS/Runtime/WeakSetPrototype.h b/Userland/Libraries/LibJS/Runtime/WeakSetPrototype.h index 31a6a2cf96..5aee2fb630 100644 --- a/Userland/Libraries/LibJS/Runtime/WeakSetPrototype.h +++ b/Userland/Libraries/LibJS/Runtime/WeakSetPrototype.h @@ -20,4 +20,10 @@ public: private: static WeakSet* typed_this(VM&, GlobalObject&); + + JS_DECLARE_NATIVE_FUNCTION(add); + JS_DECLARE_NATIVE_FUNCTION(delete_); + JS_DECLARE_NATIVE_FUNCTION(has); +}; + } diff --git a/Userland/Libraries/LibJS/Tests/builtins/WeakSet/WeakSet.prototype.add.js b/Userland/Libraries/LibJS/Tests/builtins/WeakSet/WeakSet.prototype.add.js new file mode 100644 index 0000000000..0f77e94fe6 --- /dev/null +++ b/Userland/Libraries/LibJS/Tests/builtins/WeakSet/WeakSet.prototype.add.js @@ -0,0 +1,16 @@ +test("basic functionality", () => { + expect(WeakSet.prototype.add).toHaveLength(1); + + const weakSet = new WeakSet([{ a: 1 }, { a: 2 }, { a: 3 }]); + expect(weakSet.add({ a: 4 })).toBe(weakSet); + expect(weakSet.add({ a: 1 })).toBe(weakSet); +}); + +test("invalid values", () => { + const weakSet = new WeakSet(); + [-100, Infinity, NaN, "hello", 152n].forEach(value => { + expect(() => { + weakSet.add(value); + }).toThrowWithMessage(TypeError, "is not an object"); + }); +}); diff --git a/Userland/Libraries/LibJS/Tests/builtins/WeakSet/WeakSet.prototype.delete.js b/Userland/Libraries/LibJS/Tests/builtins/WeakSet/WeakSet.prototype.delete.js new file mode 100644 index 0000000000..adfff46188 --- /dev/null +++ b/Userland/Libraries/LibJS/Tests/builtins/WeakSet/WeakSet.prototype.delete.js @@ -0,0 +1,9 @@ +test("basic functionality", () => { + expect(WeakSet.prototype.delete).toHaveLength(1); + + var original = [{ a: 1 }, { a: 2 }, { a: 3 }]; + const weakSet = new WeakSet(original); + expect(weakSet.delete(original[0])).toBeTrue(); + expect(weakSet.delete(original[0])).toBeFalse(); + expect(weakSet.delete(null)).toBeFalse(); +}); diff --git a/Userland/Libraries/LibJS/Tests/builtins/WeakSet/WeakSet.prototype.has.js b/Userland/Libraries/LibJS/Tests/builtins/WeakSet/WeakSet.prototype.has.js new file mode 100644 index 0000000000..3a8cfe021d --- /dev/null +++ b/Userland/Libraries/LibJS/Tests/builtins/WeakSet/WeakSet.prototype.has.js @@ -0,0 +1,12 @@ +test("length is 1", () => { + expect(WeakSet.prototype.has).toHaveLength(1); +}); + +test("basic functionality", () => { + var original = [{ a: 1 }, { a: 2 }, { a: 3 }]; + var weakSet = new WeakSet(original); + + expect(new WeakSet().has()).toBeFalse(); + expect(weakSet.has(original[0])).toBeTrue(); + expect(weakSet.has({ a: 1 })).toBeFalse(); +});