Reviewers: rossberg,
Description:
Fix handling of bogus receivers for Harmony collections.
[email protected]
BUG=v8:1884
TEST=mjsunit/harmony/collections
Please review this at http://codereview.chromium.org/9074003/
SVN Base: https://v8.googlecode.com/svn/branches/bleeding_edge
Affected files:
M src/collection.js
M src/macros.py
M test/mjsunit/harmony/collections.js
Index: src/collection.js
diff --git a/src/collection.js b/src/collection.js
index
d11612681e918c56f7205af23470995eddbf0e5b..fcf4d38d94f80683d276db2efdc6b047cd0aac5e
100644
--- a/src/collection.js
+++ b/src/collection.js
@@ -47,6 +47,10 @@ function SetConstructor() {
function SetAdd(key) {
+ if (!IS_SET(this)) {
+ throw MakeTypeError('incompatible_method_receiver',
+ ['Set.prototype.add', this]);
+ }
if (IS_UNDEFINED(key)) {
key = undefined_sentinel;
}
@@ -55,6 +59,10 @@ function SetAdd(key) {
function SetHas(key) {
+ if (!IS_SET(this)) {
+ throw MakeTypeError('incompatible_method_receiver',
+ ['Set.prototype.has', this]);
+ }
if (IS_UNDEFINED(key)) {
key = undefined_sentinel;
}
@@ -63,6 +71,10 @@ function SetHas(key) {
function SetDelete(key) {
+ if (!IS_SET(this)) {
+ throw MakeTypeError('incompatible_method_receiver',
+ ['Set.prototype.delete', this]);
+ }
if (IS_UNDEFINED(key)) {
key = undefined_sentinel;
}
@@ -80,6 +92,10 @@ function MapConstructor() {
function MapGet(key) {
+ if (!IS_MAP(this)) {
+ throw MakeTypeError('incompatible_method_receiver',
+ ['Map.prototype.get', this]);
+ }
if (IS_UNDEFINED(key)) {
key = undefined_sentinel;
}
@@ -88,6 +104,10 @@ function MapGet(key) {
function MapSet(key, value) {
+ if (!IS_MAP(this)) {
+ throw MakeTypeError('incompatible_method_receiver',
+ ['Map.prototype.set', this]);
+ }
if (IS_UNDEFINED(key)) {
key = undefined_sentinel;
}
@@ -96,6 +116,10 @@ function MapSet(key, value) {
function MapHas(key) {
+ if (!IS_MAP(this)) {
+ throw MakeTypeError('incompatible_method_receiver',
+ ['Map.prototype.has', this]);
+ }
if (IS_UNDEFINED(key)) {
key = undefined_sentinel;
}
@@ -104,6 +128,10 @@ function MapHas(key) {
function MapDelete(key) {
+ if (!IS_MAP(this)) {
+ throw MakeTypeError('incompatible_method_receiver',
+ ['Map.prototype.delete', this]);
+ }
if (IS_UNDEFINED(key)) {
key = undefined_sentinel;
}
@@ -126,6 +154,10 @@ function WeakMapConstructor() {
function WeakMapGet(key) {
+ if (!IS_WEAKMAP(this)) {
+ throw MakeTypeError('incompatible_method_receiver',
+ ['WeakMap.prototype.get', this]);
+ }
if (!IS_SPEC_OBJECT(key)) {
throw %MakeTypeError('invalid_weakmap_key', [this, key]);
}
@@ -134,6 +166,10 @@ function WeakMapGet(key) {
function WeakMapSet(key, value) {
+ if (!IS_WEAKMAP(this)) {
+ throw MakeTypeError('incompatible_method_receiver',
+ ['WeakMap.prototype.set', this]);
+ }
if (!IS_SPEC_OBJECT(key)) {
throw %MakeTypeError('invalid_weakmap_key', [this, key]);
}
@@ -142,6 +178,10 @@ function WeakMapSet(key, value) {
function WeakMapHas(key) {
+ if (!IS_WEAKMAP(this)) {
+ throw MakeTypeError('incompatible_method_receiver',
+ ['WeakMap.prototype.has', this]);
+ }
if (!IS_SPEC_OBJECT(key)) {
throw %MakeTypeError('invalid_weakmap_key', [this, key]);
}
@@ -150,6 +190,10 @@ function WeakMapHas(key) {
function WeakMapDelete(key) {
+ if (!IS_WEAKMAP(this)) {
+ throw MakeTypeError('incompatible_method_receiver',
+ ['WeakMap.prototype.delete', this]);
+ }
if (!IS_SPEC_OBJECT(key)) {
throw %MakeTypeError('invalid_weakmap_key', [this, key]);
}
Index: src/macros.py
diff --git a/src/macros.py b/src/macros.py
index
bf7119feaa9ab2cc71b888265ca039efda5c94f4..34b07ab235172509d51afb4dd676b29eea63bd69
100644
--- a/src/macros.py
+++ b/src/macros.py
@@ -101,6 +101,9 @@ macro IS_OBJECT(arg) = (%_IsObject(arg));
macro IS_ARRAY(arg) = (%_IsArray(arg));
macro IS_FUNCTION(arg) = (%_IsFunction(arg));
macro IS_REGEXP(arg) = (%_IsRegExp(arg));
+macro IS_SET(arg) = (%_ClassOf(arg) === 'Set');
+macro IS_MAP(arg) = (%_ClassOf(arg) === 'Map');
+macro IS_WEAKMAP(arg) = (%_ClassOf(arg) === 'WeakMap');
macro IS_DATE(arg) = (%_ClassOf(arg) === 'Date');
macro IS_NUMBER_WRAPPER(arg) = (%_ClassOf(arg) === 'Number');
macro IS_STRING_WRAPPER(arg) = (%_ClassOf(arg) === 'String');
Index: test/mjsunit/harmony/collections.js
diff --git a/test/mjsunit/harmony/collections.js
b/test/mjsunit/harmony/collections.js
index
4b435c16141b01c50bb3ca7233b053261d9ef919..52df11f97445a889bc58da658ac112bf33b4bad2
100644
--- a/test/mjsunit/harmony/collections.js
+++ b/test/mjsunit/harmony/collections.js
@@ -274,6 +274,30 @@ var o = Object.create({}, { myValue: {
assertEquals(10, o.myValue);
+// Regression test for issue 1884: Invoking any of the methods for Harmony
+// maps, sets, or weak maps, with a wrong type of receiver should be
throwing
+// a proper TypeError.
+function TestBogusReceivers(func) {
+ assertThrows(function () { func.call(undefined, {}) }, TypeError);
+ assertThrows(function () { func.call(null, {}) }, TypeError);
+ assertThrows(function () { func.call(true, {}) }, TypeError);
+ assertThrows(function () { func.call("x", {}) }, TypeError);
+ assertThrows(function () { func.call(23, {}) }, TypeError);
+ assertThrows(function () { func.call({}, {}) }, TypeError);
+}
+TestBogusReceivers(Set.prototype.add);
+TestBogusReceivers(Set.prototype.has);
+TestBogusReceivers(Set.prototype.delete);
+TestBogusReceivers(Map.prototype.get);
+TestBogusReceivers(Map.prototype.set);
+TestBogusReceivers(Map.prototype.has);
+TestBogusReceivers(Map.prototype.delete);
+TestBogusReceivers(WeakMap.prototype.get);
+TestBogusReceivers(WeakMap.prototype.set);
+TestBogusReceivers(WeakMap.prototype.has);
+TestBogusReceivers(WeakMap.prototype.delete);
+
+
// Stress Test
// There is a proposed stress-test available at the es-discuss mailing list
// which cannot be reasonably automated. Check it out by hand if you like:
--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev