From e79274abe6cfbf2cfece47022385934ea65d58b6 Mon Sep 17 00:00:00 2001 From: "mstarzinger@chromium.org" Date: Thu, 5 Jan 2012 12:55:06 +0000 Subject: [PATCH] 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 --- src/collection.js | 44 +++++++++++++++++++++++++++++ src/macros.py | 3 ++ test/mjsunit/harmony/collections.js | 34 ++++++++++++++++++++++ 3 files changed, 81 insertions(+) diff --git a/src/collection.js b/src/collection.js index d11612681..fcf4d38d9 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]); } diff --git a/src/macros.py b/src/macros.py index bf7119fea..34b07ab23 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'); diff --git a/test/mjsunit/harmony/collections.js b/test/mjsunit/harmony/collections.js index 4b435c161..412e6f14c 100644 --- a/test/mjsunit/harmony/collections.js +++ b/test/mjsunit/harmony/collections.js @@ -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: -- 2.34.1