From 72484d468b492eef1beeb5e7eff76f0add99b33a Mon Sep 17 00:00:00 2001 From: Tooru Fujisawa Date: Mon, 1 Dec 2014 17:02:15 +0900 Subject: [PATCH] Bug 804279 - Part5: Add tests for monkey-patched adder in collection constructors. r=evilpie --- .../tests/collections/Map-constructor-set.js | 204 ++++++++++++++++++ .../tests/collections/Set-constructor-add.js | 183 ++++++++++++++++ .../collections/WeakMap-constructor-set.js | 199 +++++++++++++++++ .../collections/WeakSet-constructor-add.js | 178 +++++++++++++++ 4 files changed, 764 insertions(+) create mode 100644 js/src/jit-test/tests/collections/Map-constructor-set.js create mode 100644 js/src/jit-test/tests/collections/Set-constructor-add.js create mode 100644 js/src/jit-test/tests/collections/WeakMap-constructor-set.js create mode 100644 js/src/jit-test/tests/collections/WeakSet-constructor-add.js diff --git a/js/src/jit-test/tests/collections/Map-constructor-set.js b/js/src/jit-test/tests/collections/Map-constructor-set.js new file mode 100644 index 000000000000..6aa9592a37e8 --- /dev/null +++ b/js/src/jit-test/tests/collections/Map-constructor-set.js @@ -0,0 +1,204 @@ +load(libdir + "asserts.js"); +load(libdir + "iteration.js"); + +var k1 = {}; +var v1 = 42; +var k2 = {}; +var v2 = 42; +var k3 = {}; +var v3 = 43; +var k4 = {}; +var v4 = 44; + +function test_patched() { + let orig = Map.prototype.set; + + // If adder is modified, constructor should call it. + var called = false; + + Map.prototype.set = function(k, v) { + assertEq(k, k1); + assertEq(v, v1); + orig.call(this, k2, v2); + called = true; + }; + + var arr = [[k1, v1]]; + + var m = new Map(arr); + + assertEq(called, true); + assertEq(m.size, 1); + assertEq(m.has(k1), false); + assertEq(m.has(k2), true); + assertEq(m.get(k1), undefined); + assertEq(m.get(k2), v2); + + Map.prototype.set = orig; +} + +function test_proxy1() { + let orig = Map.prototype.set; + + // If adder is modified, constructor should call it. + var called = false; + + Map.prototype.set = new Proxy(function(k, v) { + assertEq(k, k1); + assertEq(v, v1); + orig.call(this, k2, v2); + called = true; + }, {}); + + var arr = [[k1, v1]]; + + var m = new Map(arr); + + assertEq(called, true); + assertEq(m.size, 1); + assertEq(m.has(k1), false); + assertEq(m.has(k2), true); + assertEq(m.get(k1), undefined); + assertEq(m.get(k2), v2); + + Map.prototype.set = orig; +} + +function test_proxy2() { + let orig = Map.prototype.set; + + // If adder is modified, constructor should call it. + var called = false; + + Map.prototype.set = new Proxy(function() { + }, { + apply: function(target, that, args) { + var [k, v] = args; + assertEq(k, k1); + assertEq(v, v1); + orig.call(that, k2, v2); + called = true; + } + }); + + var arr = [[k1, v1]]; + + var m = new Map(arr); + + assertEq(called, true); + assertEq(m.size, 1); + assertEq(m.has(k1), false); + assertEq(m.has(k2), true); + assertEq(m.get(k1), undefined); + assertEq(m.get(k2), v2); + + Map.prototype.set = orig; +} + +function test_change1() { + let orig = Map.prototype.set; + + // Change to adder in GetIterator(..) call should be ignored. + var called = false; + var modified = false; + + var arr = [[k1, v1]]; + + var proxy_arr = new Proxy(arr, { + get: function(target, name) { + if (name == std_iterator) { + modified = true; + Map.prototype.set = function() { + called = true; + }; + } + return target[name]; + } + }); + + var m = new Map(proxy_arr); + + assertEq(modified, true); + assertEq(called, false); + assertEq(m.size, 1); + assertEq(m.has(k1), true); + assertEq(m.has(k2), false); + assertEq(m.get(k1), v1); + assertEq(m.get(k2), undefined); + + Map.prototype.set = orig; +} + +function test_change2() { + let orig = Map.prototype.set; + + // Change to adder in adder(...) call should be ignored. + var called = false; + var count = 0; + + Map.prototype.set = function(k, v) { + if (count == 0) { + assertEq(k, k1); + assertEq(v, v1); + orig.call(this, k3, v3); + Map.prototype.set = function() { + called = true; + }; + count = 1; + } else { + assertEq(k, k2); + assertEq(v, v2); + orig.call(this, k4, v4); + count = 2; + } + }; + + var arr = [[k1, v1], [k2, v2]]; + + var m = new Map(arr); + + assertEq(called, false); + assertEq(count, 2); + assertEq(m.size, 2); + assertEq(m.has(k1), false); + assertEq(m.has(k2), false); + assertEq(m.has(k3), true); + assertEq(m.has(k4), true); + assertEq(m.get(k1), undefined); + assertEq(m.get(k2), undefined); + assertEq(m.get(k3), v3); + assertEq(m.get(k4), v4); + + Map.prototype.set = orig; +} + +function test_error() { + let orig = Map.prototype.set; + + var arr = [[k1, v1]]; + + // Map should throw TypeError if adder is not callable. + Map.prototype.set = null; + assertThrowsInstanceOf(() => new Map(arr), TypeError); + Map.prototype.set = {}; + assertThrowsInstanceOf(() => new Map(arr), TypeError); + + // Map should propagate error thrown by adder. + Map.prototype.set = function() { + throw SyntaxError(); + }; + assertThrowsInstanceOf(() => new Map(arr), SyntaxError); + + Map.prototype.set = orig; +} + +function test() { + test_patched(); + test_proxy1(); + test_proxy2(); + test_change1(); + test_change2(); + test_error(); +} + +test(); diff --git a/js/src/jit-test/tests/collections/Set-constructor-add.js b/js/src/jit-test/tests/collections/Set-constructor-add.js new file mode 100644 index 000000000000..d20d0dda3fb9 --- /dev/null +++ b/js/src/jit-test/tests/collections/Set-constructor-add.js @@ -0,0 +1,183 @@ +load(libdir + "asserts.js"); +load(libdir + "iteration.js"); + +var k1 = {}; +var k2 = {}; +var k3 = {}; +var k4 = {}; + +function test_patched() { + let orig = Set.prototype.add; + + // If adder is modified, constructor should call it. + var called = false; + + Set.prototype.add = function(k, v) { + assertEq(k, k1); + orig.call(this, k2); + called = true; + }; + + var arr = [k1]; + + var m = new Set(arr); + + assertEq(called, true); + assertEq(m.size, 1); + assertEq(m.has(k1), false); + assertEq(m.has(k2), true); + + Set.prototype.add = orig; +} + +function test_proxy1() { + let orig = Set.prototype.add; + + // If adder is modified, constructor should call it. + var called = false; + + Set.prototype.add = new Proxy(function(k, v) { + assertEq(k, k1); + orig.call(this, k2); + called = true; + }, {}); + + var arr = [k1]; + + var m = new Set(arr); + + assertEq(called, true); + assertEq(m.size, 1); + assertEq(m.has(k1), false); + assertEq(m.has(k2), true); + + Set.prototype.add = orig; +} + +function test_proxy2() { + let orig = Set.prototype.add; + + // If adder is modified, constructor should call it. + var called = false; + + Set.prototype.add = new Proxy(function() { + }, { + apply: function(target, that, args) { + var [k, v] = args; + assertEq(k, k1); + orig.call(that, k2); + called = true; + } + }); + + var arr = [k1]; + + var m = new Set(arr); + + assertEq(called, true); + assertEq(m.size, 1); + assertEq(m.has(k1), false); + assertEq(m.has(k2), true); + + Set.prototype.add = orig; +} + +function test_change1() { + let orig = Set.prototype.add; + + // Change to adder in GetIterator(..) call should be ignored. + var called = false; + var modified = false; + + var arr = [k1]; + + var proxy_arr = new Proxy(arr, { + get: function(target, name) { + if (name == std_iterator) { + modified = true; + Set.prototype.add = function() { + called = true; + }; + } + return target[name]; + } + }); + + var m = new Set(proxy_arr); + + assertEq(modified, true); + assertEq(called, false); + assertEq(m.size, 1); + assertEq(m.has(k1), true); + assertEq(m.has(k2), false); + + Set.prototype.add = orig; +} + +function test_change2() { + let orig = Set.prototype.add; + + // Change to adder in adder(...) call should be ignored. + var called = false; + var count = 0; + + Set.prototype.add = function(k, v) { + if (count == 0) { + assertEq(k, k1); + orig.call(this, k3); + Set.prototype.add = function() { + called = true; + }; + count = 1; + } else { + assertEq(k, k2); + orig.call(this, k4); + count = 2; + } + }; + + var arr = [k1, k2]; + + var m = new Set(arr); + + assertEq(called, false); + assertEq(count, 2); + assertEq(m.size, 2); + assertEq(m.has(k1), false); + assertEq(m.has(k2), false); + assertEq(m.has(k3), true); + assertEq(m.has(k4), true); + + Set.prototype.add = orig; +} + +function test_error() { + let orig = Set.prototype.add; + + var arr = [k1]; + + // Set should throw TypeError if adder is not callable. + Set.prototype.add = null; + assertThrowsInstanceOf(() => new Set(arr), TypeError); + Set.prototype.add = {}; + assertThrowsInstanceOf(() => new Set(arr), TypeError); + + // Set should propagate error thrown by adder. + Set.prototype.add = function() { + throw SyntaxError(); + }; + assertThrowsInstanceOf(() => new Set(arr), SyntaxError); + + Set.prototype.add = orig; +} + +function test() { + test_patched(); + test_proxy1(); + test_proxy2(); + test_change1(); + test_change2(); + test_error(); +} + +test(); diff --git a/js/src/jit-test/tests/collections/WeakMap-constructor-set.js b/js/src/jit-test/tests/collections/WeakMap-constructor-set.js new file mode 100644 index 000000000000..bcd675533e44 --- /dev/null +++ b/js/src/jit-test/tests/collections/WeakMap-constructor-set.js @@ -0,0 +1,199 @@ +load(libdir + "asserts.js"); +load(libdir + "iteration.js"); + +var k1 = {}; +var v1 = 42; +var k2 = {}; +var v2 = 42; +var k3 = {}; +var v3 = 43; +var k4 = {}; +var v4 = 44; + +function test_patched() { + let orig = WeakMap.prototype.set; + + // If adder is modified, constructor should call it. + var called = false; + + WeakMap.prototype.set = function(k, v) { + assertEq(k, k1); + assertEq(v, v1); + orig.call(this, k2, v2); + called = true; + }; + + var arr = [[k1, v1]]; + + var m = new WeakMap(arr); + + assertEq(called, true); + assertEq(m.has(k1), false); + assertEq(m.has(k2), true); + assertEq(m.get(k1), undefined); + assertEq(m.get(k2), v2); + + WeakMap.prototype.set = orig; +} + +function test_proxy1() { + let orig = WeakMap.prototype.set; + + // If adder is modified, constructor should call it. + var called = false; + + WeakMap.prototype.set = new Proxy(function(k, v) { + assertEq(k, k1); + assertEq(v, v1); + orig.call(this, k2, v2); + called = true; + }, {}); + + var arr = [[k1, v1]]; + + var m = new WeakMap(arr); + + assertEq(called, true); + assertEq(m.has(k1), false); + assertEq(m.has(k2), true); + assertEq(m.get(k1), undefined); + assertEq(m.get(k2), v2); + + WeakMap.prototype.set = orig; +} + +function test_proxy2() { + let orig = WeakMap.prototype.set; + + // If adder is modified, constructor should call it. + var called = false; + + WeakMap.prototype.set = new Proxy(function() { + }, { + apply: function(target, that, args) { + var [k, v] = args; + assertEq(k, k1); + assertEq(v, v1); + orig.call(that, k2, v2); + called = true; + } + }); + + var arr = [[k1, v1]]; + + var m = new WeakMap(arr); + + assertEq(called, true); + assertEq(m.has(k1), false); + assertEq(m.has(k2), true); + assertEq(m.get(k1), undefined); + assertEq(m.get(k2), v2); + + WeakMap.prototype.set = orig; +} + +function test_change1() { + let orig = WeakMap.prototype.set; + + // Change to adder in GetIterator(..) call should be ignored. + var called = false; + var modified = false; + + var arr = [[k1, v1]]; + + var proxy_arr = new Proxy(arr, { + get: function(target, name) { + if (name == std_iterator) { + modified = true; + WeakMap.prototype.set = function() { + called = true; + }; + } + return target[name]; + } + }); + + var m = new WeakMap(proxy_arr); + + assertEq(modified, true); + assertEq(called, false); + assertEq(m.has(k1), true); + assertEq(m.has(k2), false); + assertEq(m.get(k1), v1); + assertEq(m.get(k2), undefined); + + WeakMap.prototype.set = orig; +} + +function test_change2() { + let orig = WeakMap.prototype.set; + + // Change to adder in adder(...) call should be ignored. + var called = false; + var count = 0; + + WeakMap.prototype.set = function(k, v) { + if (count == 0) { + assertEq(k, k1); + assertEq(v, v1); + orig.call(this, k3, v3); + WeakMap.prototype.set = function() { + called = true; + }; + count = 1; + } else { + assertEq(k, k2); + assertEq(v, v2); + orig.call(this, k4, v4); + count = 2; + } + }; + + var arr = [[k1, v1], [k2, v2]]; + + var m = new WeakMap(arr); + + assertEq(called, false); + assertEq(count, 2); + assertEq(m.has(k1), false); + assertEq(m.has(k2), false); + assertEq(m.has(k3), true); + assertEq(m.has(k4), true); + assertEq(m.get(k1), undefined); + assertEq(m.get(k2), undefined); + assertEq(m.get(k3), v3); + assertEq(m.get(k4), v4); + + WeakMap.prototype.set = orig; +} + +function test_error() { + let orig = WeakMap.prototype.set; + + var arr = [[k1, v1]]; + + // WeakMap should throw TypeError if adder is not callable. + WeakMap.prototype.set = null; + assertThrowsInstanceOf(() => new WeakMap(arr), TypeError); + WeakMap.prototype.set = {}; + assertThrowsInstanceOf(() => new WeakMap(arr), TypeError); + + // WeakMap should propagate error thrown by adder. + WeakMap.prototype.set = function() { + throw SyntaxError(); + }; + assertThrowsInstanceOf(() => new WeakMap(arr), SyntaxError); + + WeakMap.prototype.set = orig; +} + +function test() { + test_patched(); + test_proxy1(); + test_proxy2(); + test_change1(); + test_change2(); + test_error(); +} + +test(); diff --git a/js/src/jit-test/tests/collections/WeakSet-constructor-add.js b/js/src/jit-test/tests/collections/WeakSet-constructor-add.js new file mode 100644 index 000000000000..11789675f4d1 --- /dev/null +++ b/js/src/jit-test/tests/collections/WeakSet-constructor-add.js @@ -0,0 +1,178 @@ +load(libdir + "asserts.js"); +load(libdir + "iteration.js"); + +var k1 = {}; +var k2 = {}; +var k3 = {}; +var k4 = {}; + +function test_patched() { + let orig = WeakSet.prototype.add; + + // If adder is modified, constructor should call it. + var called = false; + + WeakSet.prototype.add = function(k, v) { + assertEq(k, k1); + orig.call(this, k2); + called = true; + }; + + var arr = [k1]; + + var m = new WeakSet(arr); + + assertEq(called, true); + assertEq(m.has(k1), false); + assertEq(m.has(k2), true); + + WeakSet.prototype.add = orig; +} + +function test_proxy1() { + let orig = WeakSet.prototype.add; + + // If adder is modified, constructor should call it. + var called = false; + + WeakSet.prototype.add = new Proxy(function(k, v) { + assertEq(k, k1); + orig.call(this, k2); + called = true; + }, {}); + + var arr = [k1]; + + var m = new WeakSet(arr); + + assertEq(called, true); + assertEq(m.has(k1), false); + assertEq(m.has(k2), true); + + WeakSet.prototype.add = orig; +} + +function test_proxy2() { + let orig = WeakSet.prototype.add; + + // If adder is modified, constructor should call it. + var called = false; + + WeakSet.prototype.add = new Proxy(function() { + }, { + apply: function(target, that, args) { + var [k, v] = args; + assertEq(k, k1); + orig.call(that, k2); + called = true; + } + }); + + var arr = [k1]; + + var m = new WeakSet(arr); + + assertEq(called, true); + assertEq(m.has(k1), false); + assertEq(m.has(k2), true); + + WeakSet.prototype.add = orig; +} + +function test_change1() { + let orig = WeakSet.prototype.add; + + // Change to adder in GetIterator(..) call should be ignored. + var called = false; + var modified = false; + + var arr = [k1]; + + var proxy_arr = new Proxy(arr, { + get: function(target, name) { + if (name == std_iterator) { + modified = true; + WeakSet.prototype.add = function() { + called = true; + }; + } + return target[name]; + } + }); + + var m = new WeakSet(proxy_arr); + + assertEq(modified, true); + assertEq(called, false); + assertEq(m.has(k1), true); + assertEq(m.has(k2), false); + + WeakSet.prototype.add = orig; +} + +function test_change2() { + let orig = WeakSet.prototype.add; + + // Change to adder in adder(...) call should be ignored. + var called = false; + var count = 0; + + WeakSet.prototype.add = function(k, v) { + if (count == 0) { + assertEq(k, k1); + orig.call(this, k3); + WeakSet.prototype.add = function() { + called = true; + }; + count = 1; + } else { + assertEq(k, k2); + orig.call(this, k4); + count = 2; + } + }; + + var arr = [k1, k2]; + + var m = new WeakSet(arr); + + assertEq(called, false); + assertEq(count, 2); + assertEq(m.has(k1), false); + assertEq(m.has(k2), false); + assertEq(m.has(k3), true); + assertEq(m.has(k4), true); + + WeakSet.prototype.add = orig; +} + +function test_error() { + let orig = WeakSet.prototype.add; + + var arr = [k1]; + + // WeakSet should throw TypeError if adder is not callable. + WeakSet.prototype.add = null; + assertThrowsInstanceOf(() => new WeakSet(arr), TypeError); + WeakSet.prototype.add = {}; + assertThrowsInstanceOf(() => new WeakSet(arr), TypeError); + + // WeakSet should propagate error thrown by adder. + WeakSet.prototype.add = function() { + throw SyntaxError(); + }; + assertThrowsInstanceOf(() => new WeakSet(arr), SyntaxError); + + WeakSet.prototype.add = orig; +} + +function test() { + test_patched(); + test_proxy1(); + test_proxy2(); + test_change1(); + test_change2(); + test_error(); +} + +test();