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.
1 /*
2 * Any copyright is dedicated to the Public Domain.
3 * http://creativecommons.org/licenses/publicdomain/
4 */
6 var count = 0;
8 function testCaller(obj) {
9 switch (++count) {
10 case 1:
11 case 2:
12 /*
13 * The first two times, obj is objA. The first time, we reference
14 * arguments.callee.caller before obj.go, so the caller getter must
15 * force the joined function object in the stack frame to cross the
16 * method read barrier. The second time, obj.go has been cloned and
17 * it should match the new frame's callee from the get-go.
18 */
19 assertEq(obj, objA);
20 break;
22 case 3: {
23 assertEq(obj, objB);
25 /*
26 * Store another clone of the joined function object before obj.go has
27 * been read, but after it has been invoked via objB.go(objB).
28 *
29 * In this case, arguments.callee.caller must not lie and return what
30 * is currently stored in objB.go, since that function object (objA.go)
31 * was cloned earlier, when count was 1, and it is not the function
32 * object that was truly invoked.
33 *
34 * But since the invocation of objB.go(objB) did not clone go, and the
35 * following assignment overwrote the invoked value, leaving the only
36 * reference to the joined function object for go in the stack frame's
37 * callee (argv[-2]) member, the arguments.callee.caller reference must
38 * clone a function object for the callee, store it as the callee, and
39 * return it here.
40 *
41 * It won't equal obj.go, but (implementation detail) it should have
42 * the same proto as obj.go
43 */
44 obj.go = objA.go;
46 let caller = arguments.callee.caller;
47 let obj_go = obj.go;
48 return caller != obj_go && caller.__proto__ == obj_go.__proto__;
49 }
51 case 4: {
52 assertEq(obj, objC);
54 let save = obj.go;
55 delete obj.go;
56 return arguments.callee.caller == save;
57 }
59 case 5: {
60 assertEq(obj, objD);
62 let read = obj.go;
63 break;
64 }
65 }
67 return arguments.callee.caller == obj.go;
68 }
70 function make() {
71 return {
72 go: function(obj) {
73 return testCaller(obj);
74 }
75 };
76 }
78 var objA = make(),
79 objB = make(),
80 objC = make(),
81 objD = make();
83 reportCompare(true, objA.go(objA), "1");
84 reportCompare(true, objA.go(objA), "2");
85 reportCompare(true, objB.go(objB), "3");
86 reportCompare(true, objC.go(objC), "4");
87 reportCompare(true, objD.go(objD), "5");