mirror of
https://github.com/RGBCube/serenity
synced 2025-06-01 09:18:11 +00:00
LibJS: Add spec comments to MapPrototype
This commit is contained in:
parent
2140200a19
commit
f3f78642f4
1 changed files with 112 additions and 23 deletions
|
@ -44,16 +44,35 @@ ThrowCompletionOr<void> MapPrototype::initialize(Realm& realm)
|
|||
// 24.1.3.1 Map.prototype.clear ( ), https://tc39.es/ecma262/#sec-map.prototype.clear
|
||||
JS_DEFINE_NATIVE_FUNCTION(MapPrototype::clear)
|
||||
{
|
||||
// 1. Let M be the this value.
|
||||
// 2. Perform ? RequireInternalSlot(M, [[MapData]]).
|
||||
auto map = TRY(typed_this_object(vm));
|
||||
|
||||
// 3. For each Record { [[Key]], [[Value]] } p of M.[[MapData]], do
|
||||
// a. Set p.[[Key]] to empty.
|
||||
// b. Set p.[[Value]] to empty.
|
||||
map->map_clear();
|
||||
|
||||
// 4. Return undefined.
|
||||
return js_undefined();
|
||||
}
|
||||
|
||||
// 24.1.3.3 Map.prototype.delete ( key ), https://tc39.es/ecma262/#sec-map.prototype.delete
|
||||
JS_DEFINE_NATIVE_FUNCTION(MapPrototype::delete_)
|
||||
{
|
||||
auto key = vm.argument(0);
|
||||
|
||||
// 1. Let M be the this value.
|
||||
// 2. Perform ? RequireInternalSlot(M, [[MapData]]).
|
||||
auto map = TRY(typed_this_object(vm));
|
||||
return Value(map->map_remove(vm.argument(0)));
|
||||
|
||||
// 3. For each Record { [[Key]], [[Value]] } p of M.[[MapData]], do
|
||||
// a. If p.[[Key]] is not empty and SameValueZero(p.[[Key]], key) is true, then
|
||||
// i. Set p.[[Key]] to empty.
|
||||
// ii. Set p.[[Value]] to empty.
|
||||
// iii. Return true.
|
||||
// 4. Return false.
|
||||
return Value(map->map_remove(key));
|
||||
}
|
||||
|
||||
// 24.1.3.4 Map.prototype.entries ( ), https://tc39.es/ecma262/#sec-map.prototype.entries
|
||||
|
@ -61,38 +80,80 @@ JS_DEFINE_NATIVE_FUNCTION(MapPrototype::entries)
|
|||
{
|
||||
auto& realm = *vm.current_realm();
|
||||
|
||||
// 1. Let M be the this value.
|
||||
auto map = TRY(typed_this_object(vm));
|
||||
|
||||
return MapIterator::create(realm, map, Object::PropertyKind::KeyAndValue);
|
||||
// 2. Return ? CreateMapIterator(M, key+value).
|
||||
return MapIterator::create(realm, *map, Object::PropertyKind::KeyAndValue);
|
||||
}
|
||||
|
||||
// 24.1.3.5 Map.prototype.forEach ( callbackfn [ , thisArg ] ), https://tc39.es/ecma262/#sec-map.prototype.foreach
|
||||
JS_DEFINE_NATIVE_FUNCTION(MapPrototype::for_each)
|
||||
{
|
||||
auto callbackfn = vm.argument(0);
|
||||
auto this_arg = vm.argument(1);
|
||||
|
||||
// 1. Let M be the this value.
|
||||
// 2. Perform ? RequireInternalSlot(M, [[MapData]]).
|
||||
auto map = TRY(typed_this_object(vm));
|
||||
if (!vm.argument(0).is_function())
|
||||
return vm.throw_completion<TypeError>(ErrorType::NotAFunction, TRY_OR_THROW_OOM(vm, vm.argument(0).to_string_without_side_effects()));
|
||||
auto this_value = vm.this_value();
|
||||
for (auto& entry : *map)
|
||||
TRY(call(vm, vm.argument(0).as_function(), vm.argument(1), entry.value, entry.key, this_value));
|
||||
|
||||
// 3. If IsCallable(callbackfn) is false, throw a TypeError exception.
|
||||
if (!callbackfn.is_function())
|
||||
return vm.throw_completion<TypeError>(ErrorType::NotAFunction, TRY_OR_THROW_OOM(vm, callbackfn.to_string_without_side_effects()));
|
||||
|
||||
// 4. Let entries be M.[[MapData]].
|
||||
// 5. Let numEntries be the number of elements in entries.
|
||||
// 6. Let index be 0.
|
||||
// 7. Repeat, while index < numEntries,
|
||||
for (auto& entry : *map) {
|
||||
// i. Let e be entries[index].
|
||||
// b. Set index to index + 1.
|
||||
// c. If e.[[Key]] is not empty, then
|
||||
// NOTE: This is handled by Map's IteratorImpl.
|
||||
|
||||
// i. Perform ? Call(callbackfn, thisArg, « e.[[Value]], e.[[Key]], M »).
|
||||
TRY(call(vm, callbackfn.as_function(), this_arg, entry.value, entry.key, map));
|
||||
|
||||
// ii. NOTE: The number of elements in entries may have increased during execution of callbackfn.
|
||||
// iii. Set numEntries to the number of elements in entries.
|
||||
}
|
||||
|
||||
// 8. Return undefined.
|
||||
return js_undefined();
|
||||
}
|
||||
|
||||
// 24.1.3.6 Map.prototype.get ( key ), https://tc39.es/ecma262/#sec-map.prototype.get
|
||||
JS_DEFINE_NATIVE_FUNCTION(MapPrototype::get)
|
||||
{
|
||||
auto key = vm.argument(0);
|
||||
|
||||
// 1. Let M be the this value.
|
||||
// 2. Perform ? RequireInternalSlot(M, [[MapData]]).
|
||||
auto map = TRY(typed_this_object(vm));
|
||||
auto result = map->map_get(vm.argument(0));
|
||||
if (!result.has_value())
|
||||
return js_undefined();
|
||||
return result.value();
|
||||
|
||||
// 3. For each Record { [[Key]], [[Value]] } p of M.[[MapData]], do
|
||||
// a. If p.[[Key]] is not empty and SameValueZero(p.[[Key]], key) is true, return p.[[Value]].
|
||||
auto result = map->map_get(key);
|
||||
if (result.has_value())
|
||||
return result.value();
|
||||
|
||||
// 4. Return undefined.
|
||||
return js_undefined();
|
||||
}
|
||||
|
||||
// 24.1.3.7 Map.prototype.has ( key ), https://tc39.es/ecma262/#sec-map.prototype.has
|
||||
JS_DEFINE_NATIVE_FUNCTION(MapPrototype::has)
|
||||
{
|
||||
auto key = vm.argument(0);
|
||||
|
||||
// 1. Let M be the this value.
|
||||
// 2. Perform ? RequireInternalSlot(M, [[MapData]]).
|
||||
auto map = TRY(typed_this_object(vm));
|
||||
return map->map_has(vm.argument(0));
|
||||
|
||||
// 3. For each Record { [[Key]], [[Value]] } p of M.[[MapData]], do
|
||||
// a. If p.[[Key]] is not empty and SameValueZero(p.[[Key]], key) is true, return true.
|
||||
// 4. Return false.
|
||||
return map->map_has(key);
|
||||
}
|
||||
|
||||
// 24.1.3.8 Map.prototype.keys ( ), https://tc39.es/ecma262/#sec-map.prototype.keys
|
||||
|
@ -100,37 +161,65 @@ JS_DEFINE_NATIVE_FUNCTION(MapPrototype::keys)
|
|||
{
|
||||
auto& realm = *vm.current_realm();
|
||||
|
||||
// 1. Let M be the this value.
|
||||
auto map = TRY(typed_this_object(vm));
|
||||
|
||||
return MapIterator::create(realm, map, Object::PropertyKind::Key);
|
||||
// 2. Return ? CreateMapIterator(M, key).
|
||||
return MapIterator::create(realm, *map, Object::PropertyKind::Key);
|
||||
}
|
||||
|
||||
// 24.1.3.9 Map.prototype.set ( key, value ), https://tc39.es/ecma262/#sec-map.prototype.set
|
||||
JS_DEFINE_NATIVE_FUNCTION(MapPrototype::set)
|
||||
{
|
||||
auto map = TRY(typed_this_object(vm));
|
||||
auto key = vm.argument(0);
|
||||
auto value = vm.argument(1);
|
||||
|
||||
// 1. Let M be the this value.
|
||||
// 2. Perform ? RequireInternalSlot(M, [[MapData]]).
|
||||
auto map = TRY(typed_this_object(vm));
|
||||
|
||||
// 4. If key is -0𝔽, set key to +0𝔽.
|
||||
if (key.is_negative_zero())
|
||||
key = Value(0);
|
||||
map->map_set(key, vm.argument(1));
|
||||
|
||||
// 3. For each Record { [[Key]], [[Value]] } p of M.[[MapData]], do
|
||||
// a. If p.[[Key]] is not empty and SameValueZero(p.[[Key]], key) is true, then
|
||||
// i. Set p.[[Value]] to value.
|
||||
// ii. Return M.
|
||||
// 5. Let p be the Record { [[Key]]: key, [[Value]]: value }.
|
||||
// 6. Append p to M.[[MapData]].
|
||||
map->map_set(key, value);
|
||||
|
||||
// 7. Return M.
|
||||
return map;
|
||||
}
|
||||
|
||||
// 24.1.3.10 get Map.prototype.size, https://tc39.es/ecma262/#sec-get-map.prototype.size
|
||||
JS_DEFINE_NATIVE_FUNCTION(MapPrototype::size_getter)
|
||||
{
|
||||
// 1. Let M be the this value.
|
||||
// 2. Perform ? RequireInternalSlot(M, [[MapData]]).
|
||||
auto map = TRY(typed_this_object(vm));
|
||||
|
||||
// 3. Let count be 0.
|
||||
// 4. For each Record { [[Key]], [[Value]] } p of M.[[MapData]], do
|
||||
// a. If p.[[Key]] is not empty, set count to count + 1.
|
||||
auto count = map->map_size();
|
||||
|
||||
// 5. Return 𝔽(count).
|
||||
return Value(count);
|
||||
}
|
||||
|
||||
// 24.1.3.11 Map.prototype.values ( ), https://tc39.es/ecma262/#sec-map.prototype.values
|
||||
JS_DEFINE_NATIVE_FUNCTION(MapPrototype::values)
|
||||
{
|
||||
auto& realm = *vm.current_realm();
|
||||
|
||||
// 1. Let M be the this value.
|
||||
auto map = TRY(typed_this_object(vm));
|
||||
|
||||
return MapIterator::create(realm, map, Object::PropertyKind::Value);
|
||||
}
|
||||
|
||||
// 24.1.3.10 get Map.prototype.size, https://tc39.es/ecma262/#sec-get-map.prototype.size
|
||||
JS_DEFINE_NATIVE_FUNCTION(MapPrototype::size_getter)
|
||||
{
|
||||
auto map = TRY(typed_this_object(vm));
|
||||
return Value(map->map_size());
|
||||
// 2. Return ? CreateMapIterator(M, value).
|
||||
return MapIterator::create(realm, *map, Object::PropertyKind::Value);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue