1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/js/src/tests/ecma_6/Proxy/proxy-isExtensible.js Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,94 @@ 1.4 +// Test ES6 Proxy trap compliance for Object.isExtensible() on exotic proxy 1.5 +// objects. 1.6 +var unsealed = {}; 1.7 +var sealed = Object.seal({}); 1.8 +var handler = {}; 1.9 + 1.10 +assertEq(Object.isExtensible(unsealed), true); 1.11 +assertEq(Object.isExtensible(sealed), false); 1.12 + 1.13 +var targetSealed = new Proxy(sealed, handler); 1.14 +var targetUnsealed = new Proxy(unsealed, handler); 1.15 + 1.16 +var handlerCalled = false; 1.17 + 1.18 +// without traps, forward to the target 1.19 +// First, make sure we get the obvious answer on a non-exotic target. 1.20 +assertEq(Object.isExtensible(targetSealed), false, "Must forward to target without hook."); 1.21 +assertEq(Object.isExtensible(targetUnsealed), true, "Must forward to target without hook."); 1.22 + 1.23 +// Now, keep everyone honest. What if the target itself is a proxy? 1.24 +function ensureCalled() { handlerCalled = true; return true; } 1.25 +var proxyTarget = new Proxy({}, { isExtensible : ensureCalled }); 1.26 +assertEq(Object.isExtensible(new Proxy(proxyTarget, {})), true, "Must forward to target without hook."); 1.27 +assertEq(handlerCalled, true, "Must forward to target without hook."); 1.28 + 1.29 +// with traps, makes sure that the handler is called, and that we throw if the 1.30 +// trap disagrees with the target 1.31 +function testExtensible(obj, shouldThrow, expectedResult) 1.32 +{ 1.33 + handlerCalled = false; 1.34 + if (shouldThrow) 1.35 + assertThrowsInstanceOf(function () { Object.isExtensible(obj); }, 1.36 + TypeError, "Must throw if handler and target disagree."); 1.37 + else 1.38 + assertEq(Object.isExtensible(obj), expectedResult, "Must return the correct value."); 1.39 + assertEq(handlerCalled, true, "Must call handler trap if present"); 1.40 +} 1.41 + 1.42 +// What if the trap says it's necessarily sealed? 1.43 +function fakeSealed() { handlerCalled = true; return false; } 1.44 +handler.isExtensible = fakeSealed; 1.45 +testExtensible(targetSealed, false, false); 1.46 +testExtensible(targetUnsealed, true); 1.47 + 1.48 +// What if the trap says it's never sealed? 1.49 +function fakeUnsealed() { handlerCalled = true; return true; } 1.50 +handler.isExtensible = fakeUnsealed; 1.51 +testExtensible(targetSealed, true); 1.52 +testExtensible(targetUnsealed, false, true); 1.53 + 1.54 +// make sure we are able to prevent further extensions mid-flight and throw if the 1.55 +// hook tries to lie. 1.56 +function makeSealedTruth(target) { handlerCalled = true; Object.preventExtensions(target); return false; } 1.57 +function makeSealedLie(target) { handlerCalled = true; Object.preventExtensions(target); return true; } 1.58 +handler.isExtensible = makeSealedTruth; 1.59 +testExtensible(new Proxy({}, handler), false, false); 1.60 +handler.isExtensible = makeSealedLie; 1.61 +testExtensible(new Proxy({}, handler), true); 1.62 + 1.63 +// What if the trap doesn't directly return a boolean? 1.64 +function falseyNonBool() { handlerCalled = true; return undefined; } 1.65 +handler.isExtensible = falseyNonBool; 1.66 +testExtensible(targetSealed, false, false); 1.67 +testExtensible(targetUnsealed, true); 1.68 + 1.69 +function truthyNonBool() { handlerCalled = true; return {}; } 1.70 +handler.isExtensible = truthyNonBool; 1.71 +testExtensible(targetSealed, true); 1.72 +testExtensible(targetUnsealed, false, true); 1.73 + 1.74 +// What if the trap throws? 1.75 +function ExtensibleError() { } 1.76 +ExtensibleError.prototype = new Error(); 1.77 +ExtensibleError.prototype.constructor = ExtensibleError; 1.78 +function throwFromTrap() { throw new ExtensibleError(); } 1.79 +handler.isExtensible = throwFromTrap; 1.80 + 1.81 +// exercise some other code paths and make sure that they invoke the trap and 1.82 +// can handle the ensuing error. 1.83 +assertThrowsInstanceOf(function () { Object.isExtensible(targetSealed); }, 1.84 + ExtensibleError, "Must throw if the trap does."); 1.85 +assertThrowsInstanceOf(function () { Object.isFrozen(targetSealed); }, 1.86 + ExtensibleError, "Must throw if the trap does."); 1.87 +assertThrowsInstanceOf(function () { Object.isSealed(targetSealed); }, 1.88 + ExtensibleError, "Must throw if the trap does."); 1.89 + 1.90 + 1.91 +// What if the trap likes to re-ask old questions? 1.92 +function recurse() { return Object.isExtensible(targetSealed); } 1.93 +handler.isExtensible = recurse; 1.94 +assertThrowsInstanceOf(function () { Object.isExtensible(targetSealed); }, 1.95 + InternalError, "Should allow and detect infinite recurison."); 1.96 + 1.97 +reportCompare(0, 0, "OK");