js/src/tests/ecma_6/Proxy/proxy-isExtensible.js

changeset 0
6474c204b198
     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");

mercurial