NEW: for..of iterator for CPDictionary (#3113)

This commit is contained in:
daboe01
2025-09-25 07:27:17 +02:00
committed by GitHub
parent 7f286129de
commit 17136d23f9
3 changed files with 59 additions and 1 deletions
+1 -1
View File
@@ -774,4 +774,4 @@ if (CFMutableDictionary.prototype.isa !== CPMutableDictionary)
writable: true
}
});
}
}
+19
View File
@@ -133,6 +133,25 @@ CFDictionary.prototype.valueForKey = function(/*String*/ aKey)
DISPLAY_NAME(CFDictionary.prototype.valueForKey);
// This allows the use of 'for...of' loops directly on CFDictionary instances.
CFDictionary.prototype[Symbol.iterator] = function*()
{
// Access the internal storage directly for maximum performance.
// 'this._keys' is the internal array of keys.
const keys = this._keys;
// 'this._buckets' is the internal hash map of key -> value.
const buckets = this._buckets;
// A 'for...of' loop on an array is itself a lazy and efficient way to iterate.
for (const key of keys)
{
// 'yield' pauses the generator and returns the [key, value] pair
// to the consumer (the for...of loop).
yield [key, buckets[key]];
}
};
CFDictionary.prototype.toString = function()
{
var string = "{\n",
+39
View File
@@ -484,4 +484,43 @@
[self assert:5 equals:[dict objectForKey:@"aKey"]];
}
- (void)testForOfIteration
{
var dict = @{ @"a": 1, @"b": 2, @"c": 3 };
var result = [CPMutableDictionary dictionary];
// Test basic for...of iteration
for (var [key, value] of dict)
{
[result setObject:value forKey:key];
}
[self assert:dict equals:result message:@"Dictionary should be equal after for...of iteration"];
// Test with spread syntax, a common use for iterables
var entries = [...dict];
[self assert:3 equals:entries.length message:@"Spread syntax should produce 3 entries"];
// The order is not guaranteed, so we check the contents by converting to a dictionary
var spreadDict = [CPMutableDictionary dictionary];
for (var entry of entries)
{
[spreadDict setObject:entry[1] forKey:entry[0]];
}
[self assert:dict equals:spreadDict message:@"Dictionary rebuilt from spread entries should be equal"];
// Test on an empty dictionary
var emptyDict = @{};
var iterations = 0;
for (var entry of emptyDict)
{
iterations++;
}
[self assert:0 equals:iterations message:@"for...of on an empty dictionary should not iterate"];
// Test with spread on empty dictionary
var emptyEntries = [...emptyDict];
[self assert:0 equals:emptyEntries.length message:@"Spread on an empty dictionary should produce an empty array"];
}
@end