Sat, 03 Jan 2015 20:18:00 +0100
Conditionally enable double key logic according to:
private browsing mode or privacy.thirdparty.isolate preference and
implement in GetCookieStringCommon and FindCookie where it counts...
With some reservations of how to convince FindCookie users to test
condition and pass a nullptr when disabling double key logic.
michael@0 | 1 | // Test ES6 Proxy trap compliance for Object.isExtensible() on exotic proxy |
michael@0 | 2 | // objects. |
michael@0 | 3 | var unsealed = {}; |
michael@0 | 4 | var sealed = Object.seal({}); |
michael@0 | 5 | var handler = {}; |
michael@0 | 6 | |
michael@0 | 7 | assertEq(Object.isExtensible(unsealed), true); |
michael@0 | 8 | assertEq(Object.isExtensible(sealed), false); |
michael@0 | 9 | |
michael@0 | 10 | var targetSealed = new Proxy(sealed, handler); |
michael@0 | 11 | var targetUnsealed = new Proxy(unsealed, handler); |
michael@0 | 12 | |
michael@0 | 13 | var handlerCalled = false; |
michael@0 | 14 | |
michael@0 | 15 | // without traps, forward to the target |
michael@0 | 16 | // First, make sure we get the obvious answer on a non-exotic target. |
michael@0 | 17 | assertEq(Object.isExtensible(targetSealed), false, "Must forward to target without hook."); |
michael@0 | 18 | assertEq(Object.isExtensible(targetUnsealed), true, "Must forward to target without hook."); |
michael@0 | 19 | |
michael@0 | 20 | // Now, keep everyone honest. What if the target itself is a proxy? |
michael@0 | 21 | function ensureCalled() { handlerCalled = true; return true; } |
michael@0 | 22 | var proxyTarget = new Proxy({}, { isExtensible : ensureCalled }); |
michael@0 | 23 | assertEq(Object.isExtensible(new Proxy(proxyTarget, {})), true, "Must forward to target without hook."); |
michael@0 | 24 | assertEq(handlerCalled, true, "Must forward to target without hook."); |
michael@0 | 25 | |
michael@0 | 26 | // with traps, makes sure that the handler is called, and that we throw if the |
michael@0 | 27 | // trap disagrees with the target |
michael@0 | 28 | function testExtensible(obj, shouldThrow, expectedResult) |
michael@0 | 29 | { |
michael@0 | 30 | handlerCalled = false; |
michael@0 | 31 | if (shouldThrow) |
michael@0 | 32 | assertThrowsInstanceOf(function () { Object.isExtensible(obj); }, |
michael@0 | 33 | TypeError, "Must throw if handler and target disagree."); |
michael@0 | 34 | else |
michael@0 | 35 | assertEq(Object.isExtensible(obj), expectedResult, "Must return the correct value."); |
michael@0 | 36 | assertEq(handlerCalled, true, "Must call handler trap if present"); |
michael@0 | 37 | } |
michael@0 | 38 | |
michael@0 | 39 | // What if the trap says it's necessarily sealed? |
michael@0 | 40 | function fakeSealed() { handlerCalled = true; return false; } |
michael@0 | 41 | handler.isExtensible = fakeSealed; |
michael@0 | 42 | testExtensible(targetSealed, false, false); |
michael@0 | 43 | testExtensible(targetUnsealed, true); |
michael@0 | 44 | |
michael@0 | 45 | // What if the trap says it's never sealed? |
michael@0 | 46 | function fakeUnsealed() { handlerCalled = true; return true; } |
michael@0 | 47 | handler.isExtensible = fakeUnsealed; |
michael@0 | 48 | testExtensible(targetSealed, true); |
michael@0 | 49 | testExtensible(targetUnsealed, false, true); |
michael@0 | 50 | |
michael@0 | 51 | // make sure we are able to prevent further extensions mid-flight and throw if the |
michael@0 | 52 | // hook tries to lie. |
michael@0 | 53 | function makeSealedTruth(target) { handlerCalled = true; Object.preventExtensions(target); return false; } |
michael@0 | 54 | function makeSealedLie(target) { handlerCalled = true; Object.preventExtensions(target); return true; } |
michael@0 | 55 | handler.isExtensible = makeSealedTruth; |
michael@0 | 56 | testExtensible(new Proxy({}, handler), false, false); |
michael@0 | 57 | handler.isExtensible = makeSealedLie; |
michael@0 | 58 | testExtensible(new Proxy({}, handler), true); |
michael@0 | 59 | |
michael@0 | 60 | // What if the trap doesn't directly return a boolean? |
michael@0 | 61 | function falseyNonBool() { handlerCalled = true; return undefined; } |
michael@0 | 62 | handler.isExtensible = falseyNonBool; |
michael@0 | 63 | testExtensible(targetSealed, false, false); |
michael@0 | 64 | testExtensible(targetUnsealed, true); |
michael@0 | 65 | |
michael@0 | 66 | function truthyNonBool() { handlerCalled = true; return {}; } |
michael@0 | 67 | handler.isExtensible = truthyNonBool; |
michael@0 | 68 | testExtensible(targetSealed, true); |
michael@0 | 69 | testExtensible(targetUnsealed, false, true); |
michael@0 | 70 | |
michael@0 | 71 | // What if the trap throws? |
michael@0 | 72 | function ExtensibleError() { } |
michael@0 | 73 | ExtensibleError.prototype = new Error(); |
michael@0 | 74 | ExtensibleError.prototype.constructor = ExtensibleError; |
michael@0 | 75 | function throwFromTrap() { throw new ExtensibleError(); } |
michael@0 | 76 | handler.isExtensible = throwFromTrap; |
michael@0 | 77 | |
michael@0 | 78 | // exercise some other code paths and make sure that they invoke the trap and |
michael@0 | 79 | // can handle the ensuing error. |
michael@0 | 80 | assertThrowsInstanceOf(function () { Object.isExtensible(targetSealed); }, |
michael@0 | 81 | ExtensibleError, "Must throw if the trap does."); |
michael@0 | 82 | assertThrowsInstanceOf(function () { Object.isFrozen(targetSealed); }, |
michael@0 | 83 | ExtensibleError, "Must throw if the trap does."); |
michael@0 | 84 | assertThrowsInstanceOf(function () { Object.isSealed(targetSealed); }, |
michael@0 | 85 | ExtensibleError, "Must throw if the trap does."); |
michael@0 | 86 | |
michael@0 | 87 | |
michael@0 | 88 | // What if the trap likes to re-ask old questions? |
michael@0 | 89 | function recurse() { return Object.isExtensible(targetSealed); } |
michael@0 | 90 | handler.isExtensible = recurse; |
michael@0 | 91 | assertThrowsInstanceOf(function () { Object.isExtensible(targetSealed); }, |
michael@0 | 92 | InternalError, "Should allow and detect infinite recurison."); |
michael@0 | 93 | |
michael@0 | 94 | reportCompare(0, 0, "OK"); |