| <p> |
| This page tests cached access to getters and setters. If the test passes, |
| you'll see a series of PASS messages below. |
| </p> |
| |
| <pre id="console"></pre> |
| |
| <script> |
| (function() { |
| if (window.testRunner) |
| testRunner.dumpAsText(); |
| |
| function log(s) |
| { |
| if (this.document) |
| document.getElementById("console").appendChild(document.createTextNode(s + "\n")); |
| else |
| print(s + "\n"); |
| } |
| |
| function shouldBe(a, aDescription, b) |
| { |
| if (a === b) { |
| log("PASS: " + aDescription + " should be " + b + " and is."); |
| } else { |
| log("FAIL: " + aDescription + " should be " + b + " but instead is " + a + "."); |
| } |
| } |
| |
| function testGetter(o) { |
| var result; |
| for (var i = 0; i < 10; i++) |
| result = o.length; |
| return result; |
| } |
| function testProtoGetter(o) { |
| var result; |
| for (var i = 0; i < 10; i++) |
| result = o.length; |
| return result; |
| } |
| function testProtoChainGetter(o) { |
| var result; |
| for (var i = 0; i < 10; i++) |
| result = o.length; |
| return result; |
| } |
| function getterTest(str, expected) { |
| shouldBe(eval(str), str, expected); |
| } |
| var testFunction3 = function(a,b,c){} |
| var testFunction5 = function(a,b,c,d,e){} |
| getterTest("testGetter({__proto__: {count: 'FAIL'}, get length(){ return this.count; }, count: 7})", 7); |
| getterTest("testGetter(testFunction3)", 3); |
| getterTest("testGetter(testFunction5)", 5); |
| |
| getterTest("testProtoGetter({__proto__: {count: 'FAIL', get length(){ return this.count; }}, count: 7})", 7); |
| getterTest("testProtoGetter({__proto__: testFunction3, count: 'FAIL'})", 3); |
| getterTest("testProtoGetter({__proto__: testFunction5, count: 'FAIL'})", 5); |
| |
| getterTest("testProtoChainGetter({__proto__: {__proto__: {count: 'FAIL', get length(){ return this.count; }}}, count: 7})", 7); |
| getterTest("testProtoChainGetter({__proto__: {__proto__: testFunction3}, count: 'FAIL'})", 3); |
| getterTest("testProtoChainGetter({__proto__: {__proto__: testFunction5}, count: 'FAIL'})", 5); |
| |
| function testCustomGetter(o) { |
| for (var i = 0; i < 10; i++) |
| o.source; |
| } |
| var r=/a/; |
| testCustomGetter(r); |
| var r2=/b/; |
| r2.__proto__ = r; |
| testCustomGetter(r2); |
| var r3=/c/; |
| r3.__proto__ = r2; |
| testCustomGetter(r3); |
| |
| function shouldThrow(func, errorMessage) { |
| var errorThrown = false; |
| var error = null; |
| try { |
| func(); |
| } catch (e) { |
| errorThrown = true; |
| error = e; |
| } |
| if (!errorThrown) |
| throw new Error('not thrown'); |
| if (String(error) !== errorMessage) |
| throw new Error(`bad error: ${String(error)}`); |
| } |
| |
| shouldThrow(function () { |
| testCustomGetter({__proto__: r}); |
| }, "TypeError: The RegExp.prototype.source getter can only be called on a RegExp object"); |
| shouldThrow(function () { |
| testCustomGetter({__proto__: {__proto__: r}}); |
| }, "TypeError: The RegExp.prototype.source getter can only be called on a RegExp object"); |
| })(); |
| </script> |