ES6: Map and Set needs to normalize minus zero
authorsvenpanne@chromium.org <svenpanne@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Wed, 29 Jan 2014 07:27:05 +0000 (07:27 +0000)
committersvenpanne@chromium.org <svenpanne@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Wed, 29 Jan 2014 07:27:05 +0000 (07:27 +0000)
BUG=v8:3069
LOG=Y
R=rossberg@chromium.org

Review URL: https://codereview.chromium.org/147143003

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@18892 ce2b1a6d-e550-0410-aec6-3dcde31c8c00

src/collection.js
test/mjsunit/harmony/collections.js

index 01537e8..1f7aef4 100644 (file)
@@ -40,6 +40,22 @@ var $WeakSet = global.WeakSet;
 // supported internally but required for Harmony sets and maps.
 var undefined_sentinel = {};
 
+
+// Map and Set uses SameValueZero which means that +0 and -0 should be treated
+// as the same value.
+function NormalizeKey(key) {
+  if (IS_UNDEFINED(key)) {
+    return undefined_sentinel;
+  }
+
+  if (key === 0) {
+    return 0;
+  }
+
+  return key;
+}
+
+
 // -------------------------------------------------------------------
 // Harmony Set
 
@@ -57,10 +73,7 @@ function SetAdd(key) {
     throw MakeTypeError('incompatible_method_receiver',
                         ['Set.prototype.add', this]);
   }
-  if (IS_UNDEFINED(key)) {
-    key = undefined_sentinel;
-  }
-  return %SetAdd(this, key);
+  return %SetAdd(this, NormalizeKey(key));
 }
 
 
@@ -69,10 +82,7 @@ function SetHas(key) {
     throw MakeTypeError('incompatible_method_receiver',
                         ['Set.prototype.has', this]);
   }
-  if (IS_UNDEFINED(key)) {
-    key = undefined_sentinel;
-  }
-  return %SetHas(this, key);
+  return %SetHas(this, NormalizeKey(key));
 }
 
 
@@ -81,9 +91,7 @@ function SetDelete(key) {
     throw MakeTypeError('incompatible_method_receiver',
                         ['Set.prototype.delete', this]);
   }
-  if (IS_UNDEFINED(key)) {
-    key = undefined_sentinel;
-  }
+  key = NormalizeKey(key);
   if (%SetHas(this, key)) {
     %SetDelete(this, key);
     return true;
@@ -151,10 +159,7 @@ function MapGet(key) {
     throw MakeTypeError('incompatible_method_receiver',
                         ['Map.prototype.get', this]);
   }
-  if (IS_UNDEFINED(key)) {
-    key = undefined_sentinel;
-  }
-  return %MapGet(this, key);
+  return %MapGet(this, NormalizeKey(key));
 }
 
 
@@ -163,10 +168,7 @@ function MapSet(key, value) {
     throw MakeTypeError('incompatible_method_receiver',
                         ['Map.prototype.set', this]);
   }
-  if (IS_UNDEFINED(key)) {
-    key = undefined_sentinel;
-  }
-  return %MapSet(this, key, value);
+  return %MapSet(this, NormalizeKey(key), value);
 }
 
 
@@ -175,10 +177,7 @@ function MapHas(key) {
     throw MakeTypeError('incompatible_method_receiver',
                         ['Map.prototype.has', this]);
   }
-  if (IS_UNDEFINED(key)) {
-    key = undefined_sentinel;
-  }
-  return %MapHas(this, key);
+  return %MapHas(this, NormalizeKey(key));
 }
 
 
@@ -187,10 +186,7 @@ function MapDelete(key) {
     throw MakeTypeError('incompatible_method_receiver',
                         ['Map.prototype.delete', this]);
   }
-  if (IS_UNDEFINED(key)) {
-    key = undefined_sentinel;
-  }
-  return %MapDelete(this, key);
+  return %MapDelete(this, NormalizeKey(key));
 }
 
 
index 04a5cdc..7e95b9e 100644 (file)
@@ -484,3 +484,25 @@ for (var i = 9; i >= 0; i--) {
   w.clear();
   assertFalse(w.has(k));
 })();
+
+
+(function TestMinusZeroSet() {
+  var m = new Set();
+  m.add(0);
+  m.add(-0);
+  assertEquals(1, m.size);
+  assertTrue(m.has(0));
+  assertTrue(m.has(-0));
+})();
+
+
+(function TestMinusZeroMap() {
+  var m = new Map();
+  m.set(0, 'plus');
+  m.set(-0, 'minus');
+  assertEquals(1, m.size);
+  assertTrue(m.has(0));
+  assertTrue(m.has(-0));
+  assertEquals('minus', m.get(0));
+  assertEquals('minus', m.get(-0));
+})();