WeakSetPrototype.cpp 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103
  1. /*
  2. * Copyright (c) 2021-2022, Idan Horowitz <idan.horowitz@serenityos.org>
  3. *
  4. * SPDX-License-Identifier: BSD-2-Clause
  5. */
  6. #include <AK/HashTable.h>
  7. #include <AK/TypeCasts.h>
  8. #include <LibJS/Runtime/AbstractOperations.h>
  9. #include <LibJS/Runtime/WeakSetPrototype.h>
  10. namespace JS {
  11. GC_DEFINE_ALLOCATOR(WeakSetPrototype);
  12. WeakSetPrototype::WeakSetPrototype(Realm& realm)
  13. : PrototypeObject(realm.intrinsics().object_prototype())
  14. {
  15. }
  16. void WeakSetPrototype::initialize(Realm& realm)
  17. {
  18. auto& vm = this->vm();
  19. Base::initialize(realm);
  20. u8 attr = Attribute::Writable | Attribute::Configurable;
  21. define_native_function(realm, vm.names.add, add, 1, attr);
  22. define_native_function(realm, vm.names.delete_, delete_, 1, attr);
  23. define_native_function(realm, vm.names.has, has, 1, attr);
  24. // 24.4.3.5 WeakSet.prototype [ @@toStringTag ], https://tc39.es/ecma262/#sec-weakset.prototype-@@tostringtag
  25. define_direct_property(vm.well_known_symbol_to_string_tag(), PrimitiveString::create(vm, vm.names.WeakSet.as_string()), Attribute::Configurable);
  26. }
  27. // 24.4.3.1 WeakSet.prototype.add ( value ), https://tc39.es/ecma262/#sec-weakset.prototype.add
  28. JS_DEFINE_NATIVE_FUNCTION(WeakSetPrototype::add)
  29. {
  30. auto value = vm.argument(0);
  31. // 1. Let S be the this value.
  32. // 2. Perform ? RequireInternalSlot(S, [[WeakSetData]]).
  33. auto weak_set = TRY(typed_this_object(vm));
  34. // 3. If CanBeHeldWeakly(value) is false, throw a TypeError exception.
  35. if (!can_be_held_weakly(value))
  36. return vm.throw_completion<TypeError>(ErrorType::CannotBeHeldWeakly, value.to_string_without_side_effects());
  37. // 4. For each element e of S.[[WeakSetData]], do
  38. // a. If e is not empty and SameValue(e, value) is true, then
  39. // i. Return S.
  40. // 5. Append value to S.[[WeakSetData]].
  41. weak_set->values().set(&value.as_cell(), AK::HashSetExistingEntryBehavior::Keep);
  42. // 6. Return S.
  43. return weak_set;
  44. }
  45. // 24.4.3.3 WeakSet.prototype.delete ( value ), https://tc39.es/ecma262/#sec-weakset.prototype.delete
  46. JS_DEFINE_NATIVE_FUNCTION(WeakSetPrototype::delete_)
  47. {
  48. auto value = vm.argument(0);
  49. // 1. Let S be the this value.
  50. // 2. Perform ? RequireInternalSlot(S, [[WeakSetData]]).
  51. auto weak_set = TRY(typed_this_object(vm));
  52. // 3. If CanBeHeldWeakly(value) is false, return false.
  53. if (!can_be_held_weakly(value))
  54. return Value(false);
  55. // 4. For each element e of S.[[WeakSetData]], do
  56. // a. If e is not empty and SameValue(e, value) is true, then
  57. // i. Replace the element of S.[[WeakSetData]] whose value is e with an element whose value is empty.
  58. // ii. Return true.
  59. // 5. Return false.
  60. return Value(weak_set->values().remove(&value.as_cell()));
  61. }
  62. // 24.4.3.4 WeakSet.prototype.has ( value ), https://tc39.es/ecma262/#sec-weakset.prototype.has
  63. JS_DEFINE_NATIVE_FUNCTION(WeakSetPrototype::has)
  64. {
  65. auto value = vm.argument(0);
  66. // 1. Let S be the this value.
  67. // 2. Perform ? RequireInternalSlot(S, [[WeakSetData]]).
  68. auto weak_set = TRY(typed_this_object(vm));
  69. // 3. If CanBeHeldWeakly(value) is false, return false.
  70. if (!can_be_held_weakly(value))
  71. return Value(false);
  72. // 4. For each element e of S.[[WeakSetData]], do
  73. // a. If e is not empty and SameValue(e, value) is true, return true.
  74. auto& values = weak_set->values();
  75. auto result = values.find(&value.as_cell());
  76. if (result != values.end())
  77. return Value(true);
  78. // 5. Return false.
  79. return Value(false);
  80. }
  81. }