WeakMapPrototype.cpp 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132
  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/WeakMapPrototype.h>
  10. namespace JS {
  11. GC_DEFINE_ALLOCATOR(WeakMapPrototype);
  12. WeakMapPrototype::WeakMapPrototype(Realm& realm)
  13. : PrototypeObject(realm.intrinsics().object_prototype())
  14. {
  15. }
  16. void WeakMapPrototype::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.delete_, delete_, 1, attr);
  22. define_native_function(realm, vm.names.get, get, 1, attr);
  23. define_native_function(realm, vm.names.has, has, 1, attr);
  24. define_native_function(realm, vm.names.set, set, 2, attr);
  25. // 24.3.3.6 WeakMap.prototype [ @@toStringTag ], https://tc39.es/ecma262/#sec-weakmap.prototype-@@tostringtag
  26. define_direct_property(vm.well_known_symbol_to_string_tag(), PrimitiveString::create(vm, vm.names.WeakMap.as_string()), Attribute::Configurable);
  27. }
  28. // 24.3.3.2 WeakMap.prototype.delete ( key ), https://tc39.es/ecma262/#sec-weakmap.prototype.delete
  29. JS_DEFINE_NATIVE_FUNCTION(WeakMapPrototype::delete_)
  30. {
  31. auto key = vm.argument(0);
  32. // 1. Let M be the this value.
  33. // 2. Perform ? RequireInternalSlot(M, [[WeakMapData]]).
  34. auto weak_map = TRY(typed_this_object(vm));
  35. // 3. If CanBeHeldWeakly(key) is false, return false.
  36. if (!can_be_held_weakly(key))
  37. return Value(false);
  38. // 4. For each Record { [[Key]], [[Value]] } p of M.[[WeakMapData]], do
  39. // a. If p.[[Key]] is not empty and SameValue(p.[[Key]], key) is true, then
  40. // i. Set p.[[Key]] to empty.
  41. // ii. Set p.[[Value]] to empty.
  42. // iii. Return true.
  43. // 5. Return false.
  44. return Value(weak_map->values().remove(&key.as_cell()));
  45. }
  46. // 24.3.3.3 WeakMap.prototype.get ( key ), https://tc39.es/ecma262/#sec-weakmap.prototype.get
  47. JS_DEFINE_NATIVE_FUNCTION(WeakMapPrototype::get)
  48. {
  49. auto key = vm.argument(0);
  50. // 1. Let M be the this value.
  51. // 2. Perform ? RequireInternalSlot(M, [[WeakMapData]]).
  52. auto weak_map = TRY(typed_this_object(vm));
  53. // 3. If CanBeHeldWeakly(key) is false, return undefined.
  54. if (!can_be_held_weakly(key))
  55. return js_undefined();
  56. // 4. For each Record { [[Key]], [[Value]] } p of M.[[WeakMapData]], do
  57. // a. If p.[[Key]] is not empty and SameValue(p.[[Key]], key) is true, return p.[[Value]].
  58. auto& values = weak_map->values();
  59. auto result = values.find(&key.as_cell());
  60. if (result != values.end())
  61. return result->value;
  62. // 5. Return undefined.
  63. return js_undefined();
  64. }
  65. // 24.3.3.4 WeakMap.prototype.has ( key ), https://tc39.es/ecma262/#sec-weakmap.prototype.has
  66. JS_DEFINE_NATIVE_FUNCTION(WeakMapPrototype::has)
  67. {
  68. auto key = vm.argument(0);
  69. // 1. Let M be the this value.
  70. // 2. Perform ? RequireInternalSlot(M, [[WeakMapData]]).
  71. auto weak_map = TRY(typed_this_object(vm));
  72. // 3. If CanBeHeldWeakly(key) is false, return false.
  73. if (!can_be_held_weakly(key))
  74. return Value(false);
  75. // 4. For each Record { [[Key]], [[Value]] } p of M.[[WeakMapData]], do
  76. // a. If p.[[Key]] is not empty and SameValue(p.[[Key]], key) is true, return true.
  77. auto& values = weak_map->values();
  78. auto result = values.find(&key.as_cell());
  79. if (result != values.end())
  80. return Value(true);
  81. // 5. Return false.
  82. return Value(false);
  83. }
  84. // 24.3.3.5 WeakMap.prototype.set ( key, value ), https://tc39.es/ecma262/#sec-weakmap.prototype.set
  85. JS_DEFINE_NATIVE_FUNCTION(WeakMapPrototype::set)
  86. {
  87. auto key = vm.argument(0);
  88. auto value = vm.argument(1);
  89. // 1. Let M be the this value.
  90. // 2. Perform ? RequireInternalSlot(M, [[WeakMapData]]).
  91. auto weak_map = TRY(typed_this_object(vm));
  92. // 3. If CanBeHeldWeakly(key) is false, throw a TypeError exception.
  93. if (!can_be_held_weakly(key))
  94. return vm.throw_completion<TypeError>(ErrorType::CannotBeHeldWeakly, value.to_string_without_side_effects());
  95. // 4. For each Record { [[Key]], [[Value]] } p of M.[[WeakMapData]], do
  96. // a. If p.[[Key]] is not empty and SameValue(p.[[Key]], key) is true, then
  97. // i. Set p.[[Value]] to value.
  98. // ii. Return M.
  99. // 5. Let p be the Record { [[Key]]: key, [[Value]]: value }.
  100. // 6. Append p to M.[[WeakMapData]].
  101. weak_map->values().set(&key.as_cell(), value);
  102. // 7. Return M.
  103. return weak_map;
  104. }
  105. }