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 /* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
5 #include "jsapi-tests/tests.h"
7 static const unsigned BufferSize = 20;
8 static unsigned FinalizeCalls = 0;
9 static JSFinalizeStatus StatusBuffer[BufferSize];
10 static bool IsCompartmentGCBuffer[BufferSize];
12 BEGIN_TEST(testGCFinalizeCallback)
13 {
14 JS_SetGCParameter(rt, JSGC_MODE, JSGC_MODE_INCREMENTAL);
15 JS_SetFinalizeCallback(rt, FinalizeCallback);
17 /* Full GC, non-incremental. */
18 FinalizeCalls = 0;
19 JS_GC(rt);
20 CHECK(rt->gcIsFull);
21 CHECK(checkSingleGroup());
22 CHECK(checkFinalizeStatus());
23 CHECK(checkFinalizeIsCompartmentGC(false));
25 /* Full GC, incremental. */
26 FinalizeCalls = 0;
27 JS::PrepareForFullGC(rt);
28 JS::IncrementalGC(rt, JS::gcreason::API, 1000000);
29 CHECK(rt->gcIncrementalState == js::gc::NO_INCREMENTAL);
30 CHECK(rt->gcIsFull);
31 CHECK(checkMultipleGroups());
32 CHECK(checkFinalizeStatus());
33 CHECK(checkFinalizeIsCompartmentGC(false));
35 JS::RootedObject global1(cx, createGlobal());
36 JS::RootedObject global2(cx, createGlobal());
37 JS::RootedObject global3(cx, createGlobal());
38 CHECK(global1);
39 CHECK(global2);
40 CHECK(global3);
42 /* Compartment GC, non-incremental, single compartment. */
43 FinalizeCalls = 0;
44 JS::PrepareZoneForGC(global1->zone());
45 JS::GCForReason(rt, JS::gcreason::API);
46 CHECK(!rt->gcIsFull);
47 CHECK(checkSingleGroup());
48 CHECK(checkFinalizeStatus());
49 CHECK(checkFinalizeIsCompartmentGC(true));
51 /* Compartment GC, non-incremental, multiple compartments. */
52 FinalizeCalls = 0;
53 JS::PrepareZoneForGC(global1->zone());
54 JS::PrepareZoneForGC(global2->zone());
55 JS::PrepareZoneForGC(global3->zone());
56 JS::GCForReason(rt, JS::gcreason::API);
57 CHECK(!rt->gcIsFull);
58 CHECK(checkSingleGroup());
59 CHECK(checkFinalizeStatus());
60 CHECK(checkFinalizeIsCompartmentGC(true));
62 /* Compartment GC, incremental, single compartment. */
63 FinalizeCalls = 0;
64 JS::PrepareZoneForGC(global1->zone());
65 JS::IncrementalGC(rt, JS::gcreason::API, 1000000);
66 CHECK(rt->gcIncrementalState == js::gc::NO_INCREMENTAL);
67 CHECK(!rt->gcIsFull);
68 CHECK(checkSingleGroup());
69 CHECK(checkFinalizeStatus());
70 CHECK(checkFinalizeIsCompartmentGC(true));
72 /* Compartment GC, incremental, multiple compartments. */
73 FinalizeCalls = 0;
74 JS::PrepareZoneForGC(global1->zone());
75 JS::PrepareZoneForGC(global2->zone());
76 JS::PrepareZoneForGC(global3->zone());
77 JS::IncrementalGC(rt, JS::gcreason::API, 1000000);
78 CHECK(rt->gcIncrementalState == js::gc::NO_INCREMENTAL);
79 CHECK(!rt->gcIsFull);
80 CHECK(checkMultipleGroups());
81 CHECK(checkFinalizeStatus());
82 CHECK(checkFinalizeIsCompartmentGC(true));
84 #ifdef JS_GC_ZEAL
86 /* Full GC with reset due to new compartment, becoming compartment GC. */
88 FinalizeCalls = 0;
89 JS_SetGCZeal(cx, 9, 1000000);
90 JS::PrepareForFullGC(rt);
91 js::GCDebugSlice(rt, true, 1);
92 CHECK(rt->gcIncrementalState == js::gc::MARK);
93 CHECK(rt->gcIsFull);
95 JS::RootedObject global4(cx, createGlobal());
96 js::GCDebugSlice(rt, true, 1);
97 CHECK(rt->gcIncrementalState == js::gc::NO_INCREMENTAL);
98 CHECK(!rt->gcIsFull);
99 CHECK(checkMultipleGroups());
100 CHECK(checkFinalizeStatus());
102 for (unsigned i = 0; i < FinalizeCalls - 1; ++i)
103 CHECK(!IsCompartmentGCBuffer[i]);
104 CHECK(IsCompartmentGCBuffer[FinalizeCalls - 1]);
106 JS_SetGCZeal(cx, 0, 0);
108 #endif
110 /*
111 * Make some use of the globals here to ensure the compiler doesn't optimize
112 * them away in release builds, causing the compartments to be collected and
113 * the test to fail.
114 */
115 CHECK(JS_IsGlobalObject(global1));
116 CHECK(JS_IsGlobalObject(global2));
117 CHECK(JS_IsGlobalObject(global3));
119 JS_SetFinalizeCallback(rt, nullptr);
120 return true;
121 }
123 bool checkSingleGroup()
124 {
125 CHECK(FinalizeCalls < BufferSize);
126 CHECK(FinalizeCalls == 3);
127 return true;
128 }
130 bool checkMultipleGroups()
131 {
132 CHECK(FinalizeCalls < BufferSize);
133 CHECK(FinalizeCalls % 2 == 1);
134 CHECK((FinalizeCalls - 1) / 2 > 1);
135 return true;
136 }
138 bool checkFinalizeStatus()
139 {
140 /*
141 * The finalize callback should be called twice for each compartment group
142 * finalized, with status JSFINALIZE_GROUP_START and JSFINALIZE_GROUP_END,
143 * and then once more with JSFINALIZE_COLLECTION_END.
144 */
146 for (unsigned i = 0; i < FinalizeCalls - 1; i += 2) {
147 CHECK(StatusBuffer[i] == JSFINALIZE_GROUP_START);
148 CHECK(StatusBuffer[i + 1] == JSFINALIZE_GROUP_END);
149 }
151 CHECK(StatusBuffer[FinalizeCalls - 1] == JSFINALIZE_COLLECTION_END);
153 return true;
154 }
156 bool checkFinalizeIsCompartmentGC(bool isCompartmentGC)
157 {
158 for (unsigned i = 0; i < FinalizeCalls; ++i)
159 CHECK(IsCompartmentGCBuffer[i] == isCompartmentGC);
161 return true;
162 }
164 static void
165 FinalizeCallback(JSFreeOp *fop, JSFinalizeStatus status, bool isCompartmentGC)
166 {
167 if (FinalizeCalls < BufferSize) {
168 StatusBuffer[FinalizeCalls] = status;
169 IsCompartmentGCBuffer[FinalizeCalls] = isCompartmentGC;
170 }
171 ++FinalizeCalls;
172 }
173 END_TEST(testGCFinalizeCallback)