Fix handling of bogus receivers for Harmony collections.

R=rossberg@chromium.org
BUG=v8:1884
TEST=mjsunit/harmony/collections

Review URL: http://codereview.chromium.org/9074003

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@10342 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
mstarzinger@chromium.org 2012-01-05 12:55:06 +00:00
parent 5253363cc2
commit e79274abe6
3 changed files with 81 additions and 0 deletions

View File

@ -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]);
}

View File

@ -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');

View File

@ -274,6 +274,40 @@ 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.
var alwaysBogus = [ undefined, null, true, "x", 23, {} ];
var bogusReceiversTestSet = [
{ proto: Set.prototype,
funcs: [ 'add', 'has', 'delete' ],
receivers: alwaysBogus.concat([ new Map, new WeakMap ]),
},
{ proto: Map.prototype,
funcs: [ 'get', 'set', 'has', 'delete' ],
receivers: alwaysBogus.concat([ new Set, new WeakMap ]),
},
{ proto: WeakMap.prototype,
funcs: [ 'get', 'set', 'has', 'delete' ],
receivers: alwaysBogus.concat([ new Set, new Map ]),
},
];
function TestBogusReceivers(testSet) {
for (var i = 0; i < testSet.length; i++) {
var proto = testSet[i].proto;
var funcs = testSet[i].funcs;
var receivers = testSet[i].receivers;
for (var j = 0; j < funcs.length; j++) {
var func = proto[funcs[j]];
for (var k = 0; k < receivers.length; k++) {
assertThrows(function () { func.call(receivers[k], {}) }, TypeError);
}
}
}
}
TestBogusReceivers(bogusReceiversTestSet);
// 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: