diff --git a/js/public/HashTable.h b/js/public/HashTable.h index 9011eeac1a74..29a3956fd3b9 100644 --- a/js/public/HashTable.h +++ b/js/public/HashTable.h @@ -1070,13 +1070,21 @@ class HashTable : private AllocPolicy bool rekeyed; bool removed; - /* Not copyable. */ + // Enum is movable but not copyable. Enum(const Enum&) = delete; void operator=(const Enum&) = delete; public: - template explicit - Enum(Map& map) : Range(map.all()), table_(map.impl), rekeyed(false), removed(false) {} + template + explicit Enum(Map& map) + : Range(map.all()), table_(map.impl), rekeyed(false), removed(false) {} + + MOZ_IMPLICIT Enum(Enum&& other) + : Range(other), table_(other.table_), rekeyed(other.rekeyed), removed(other.removed) + { + other.rekeyed = false; + other.removed = false; + } // Removes the |front()| element from the table, leaving |front()| // invalid until the next call to |popFront()|. For example: diff --git a/js/src/jsapi-tests/testHashTable.cpp b/js/src/jsapi-tests/testHashTable.cpp index 0f01165bf2f2..6229a584a5b7 100644 --- a/js/src/jsapi-tests/testHashTable.cpp +++ b/js/src/jsapi-tests/testHashTable.cpp @@ -6,6 +6,8 @@ #include "js/Utility.h" #include "jsapi-tests/tests.h" +#include "mozilla/Move.h" + //#define FUZZ typedef js::HashMap, js::SystemAllocPolicy> IntMap; @@ -388,3 +390,45 @@ BEGIN_TEST(testHashMapLookupWithDefaultOOM) END_TEST(testHashMapLookupWithDefaultOOM) #endif // defined(DEBUG) + +BEGIN_TEST(testHashTableMovableEnum) +{ + CHECK(set.init()); + + // Exercise returning a hash table Enum object from a function. + + CHECK(set.put(1)); + for (auto e = enumerateSet(); !e.empty(); e.popFront()) + e.removeFront(); + CHECK(set.count() == 0); + + // Test moving an Enum object explicitly. + + CHECK(set.put(1)); + CHECK(set.put(2)); + CHECK(set.put(3)); + CHECK(set.count() == 3); + { + auto e1 = IntSet::Enum(set); + CHECK(!e1.empty()); + e1.removeFront(); + e1.popFront(); + + auto e2 = mozilla::Move(e1); + CHECK(!e2.empty()); + e2.removeFront(); + e2.popFront(); + } + + CHECK(set.count() == 1); + return true; +} + +IntSet set; + +IntSet::Enum enumerateSet() +{ + return IntSet::Enum(set); +} + +END_TEST(testHashTableMovableEnum)