|
1 /* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */ |
|
2 /* This Source Code Form is subject to the terms of the Mozilla Public |
|
3 * License, v. 2.0. If a copy of the MPL was not distributed with this file, |
|
4 * You can obtain one at http://mozilla.org/MPL/2.0/. */ |
|
5 |
|
6 #ifndef mozilla_dom_workers_workers_h__ |
|
7 #define mozilla_dom_workers_workers_h__ |
|
8 |
|
9 #include "jsapi.h" |
|
10 #include "mozilla/Attributes.h" |
|
11 #include "mozilla/Mutex.h" |
|
12 #include <stdint.h> |
|
13 #include "nsAutoPtr.h" |
|
14 #include "nsCOMPtr.h" |
|
15 #include "nsDebug.h" |
|
16 #include "nsString.h" |
|
17 |
|
18 #define BEGIN_WORKERS_NAMESPACE \ |
|
19 namespace mozilla { namespace dom { namespace workers { |
|
20 #define END_WORKERS_NAMESPACE \ |
|
21 } /* namespace workers */ } /* namespace dom */ } /* namespace mozilla */ |
|
22 #define USING_WORKERS_NAMESPACE \ |
|
23 using namespace mozilla::dom::workers; |
|
24 |
|
25 #define WORKERS_SHUTDOWN_TOPIC "web-workers-shutdown" |
|
26 |
|
27 class nsIScriptContext; |
|
28 class nsPIDOMWindow; |
|
29 |
|
30 BEGIN_WORKERS_NAMESPACE |
|
31 |
|
32 class WorkerPrivate; |
|
33 |
|
34 struct PrivatizableBase |
|
35 { }; |
|
36 |
|
37 #ifdef DEBUG |
|
38 void |
|
39 AssertIsOnMainThread(); |
|
40 #else |
|
41 inline void |
|
42 AssertIsOnMainThread() |
|
43 { } |
|
44 #endif |
|
45 |
|
46 struct JSSettings |
|
47 { |
|
48 enum { |
|
49 // All the GC parameters that we support. |
|
50 JSSettings_JSGC_MAX_BYTES = 0, |
|
51 JSSettings_JSGC_MAX_MALLOC_BYTES, |
|
52 JSSettings_JSGC_HIGH_FREQUENCY_TIME_LIMIT, |
|
53 JSSettings_JSGC_LOW_FREQUENCY_HEAP_GROWTH, |
|
54 JSSettings_JSGC_HIGH_FREQUENCY_HEAP_GROWTH_MIN, |
|
55 JSSettings_JSGC_HIGH_FREQUENCY_HEAP_GROWTH_MAX, |
|
56 JSSettings_JSGC_HIGH_FREQUENCY_LOW_LIMIT, |
|
57 JSSettings_JSGC_HIGH_FREQUENCY_HIGH_LIMIT, |
|
58 JSSettings_JSGC_ALLOCATION_THRESHOLD, |
|
59 JSSettings_JSGC_SLICE_TIME_BUDGET, |
|
60 JSSettings_JSGC_DYNAMIC_HEAP_GROWTH, |
|
61 JSSettings_JSGC_DYNAMIC_MARK_SLICE, |
|
62 // JSGC_MODE not supported |
|
63 |
|
64 // This must be last so that we get an accurate count. |
|
65 kGCSettingsArraySize |
|
66 }; |
|
67 |
|
68 struct JSGCSetting |
|
69 { |
|
70 JSGCParamKey key; |
|
71 uint32_t value; |
|
72 |
|
73 JSGCSetting() |
|
74 : key(static_cast<JSGCParamKey>(-1)), value(0) |
|
75 { } |
|
76 |
|
77 bool |
|
78 IsSet() const |
|
79 { |
|
80 return key != static_cast<JSGCParamKey>(-1); |
|
81 } |
|
82 |
|
83 void |
|
84 Unset() |
|
85 { |
|
86 key = static_cast<JSGCParamKey>(-1); |
|
87 value = 0; |
|
88 } |
|
89 }; |
|
90 |
|
91 // There are several settings that we know we need so it makes sense to |
|
92 // preallocate here. |
|
93 typedef JSGCSetting JSGCSettingsArray[kGCSettingsArraySize]; |
|
94 |
|
95 // Settings that change based on chrome/content context. |
|
96 struct JSContentChromeSettings |
|
97 { |
|
98 JS::ContextOptions contextOptions; |
|
99 JS::CompartmentOptions compartmentOptions; |
|
100 int32_t maxScriptRuntime; |
|
101 |
|
102 JSContentChromeSettings() |
|
103 : contextOptions(), compartmentOptions(), maxScriptRuntime(0) |
|
104 { } |
|
105 }; |
|
106 |
|
107 JSContentChromeSettings chrome; |
|
108 JSContentChromeSettings content; |
|
109 JSGCSettingsArray gcSettings; |
|
110 JS::RuntimeOptions runtimeOptions; |
|
111 |
|
112 #ifdef JS_GC_ZEAL |
|
113 uint8_t gcZeal; |
|
114 uint32_t gcZealFrequency; |
|
115 #endif |
|
116 |
|
117 JSSettings() |
|
118 #ifdef JS_GC_ZEAL |
|
119 : gcZeal(0), gcZealFrequency(0) |
|
120 #endif |
|
121 { |
|
122 for (uint32_t index = 0; index < ArrayLength(gcSettings); index++) { |
|
123 new (gcSettings + index) JSGCSetting(); |
|
124 } |
|
125 } |
|
126 |
|
127 bool |
|
128 ApplyGCSetting(JSGCParamKey aKey, uint32_t aValue) |
|
129 { |
|
130 JSSettings::JSGCSetting* firstEmptySetting = nullptr; |
|
131 JSSettings::JSGCSetting* foundSetting = nullptr; |
|
132 |
|
133 for (uint32_t index = 0; index < ArrayLength(gcSettings); index++) { |
|
134 JSSettings::JSGCSetting& setting = gcSettings[index]; |
|
135 if (setting.key == aKey) { |
|
136 foundSetting = &setting; |
|
137 break; |
|
138 } |
|
139 if (!firstEmptySetting && !setting.IsSet()) { |
|
140 firstEmptySetting = &setting; |
|
141 } |
|
142 } |
|
143 |
|
144 if (aValue) { |
|
145 if (!foundSetting) { |
|
146 foundSetting = firstEmptySetting; |
|
147 if (!foundSetting) { |
|
148 NS_ERROR("Not enough space for this value!"); |
|
149 return false; |
|
150 } |
|
151 } |
|
152 foundSetting->key = aKey; |
|
153 foundSetting->value = aValue; |
|
154 return true; |
|
155 } |
|
156 |
|
157 if (foundSetting) { |
|
158 foundSetting->Unset(); |
|
159 return true; |
|
160 } |
|
161 |
|
162 return false; |
|
163 } |
|
164 }; |
|
165 |
|
166 enum WorkerPreference |
|
167 { |
|
168 WORKERPREF_DUMP = 0, // browser.dom.window.dump.enabled |
|
169 WORKERPREF_COUNT |
|
170 }; |
|
171 |
|
172 // All of these are implemented in RuntimeService.cpp |
|
173 bool |
|
174 ResolveWorkerClasses(JSContext* aCx, JS::Handle<JSObject*> aObj, JS::Handle<jsid> aId, |
|
175 JS::MutableHandle<JSObject*> aObjp); |
|
176 |
|
177 void |
|
178 CancelWorkersForWindow(nsPIDOMWindow* aWindow); |
|
179 |
|
180 void |
|
181 SuspendWorkersForWindow(nsPIDOMWindow* aWindow); |
|
182 |
|
183 void |
|
184 ResumeWorkersForWindow(nsPIDOMWindow* aWindow); |
|
185 |
|
186 class WorkerTask |
|
187 { |
|
188 protected: |
|
189 WorkerTask() |
|
190 { } |
|
191 |
|
192 virtual ~WorkerTask() |
|
193 { } |
|
194 |
|
195 public: |
|
196 NS_INLINE_DECL_THREADSAFE_REFCOUNTING(WorkerTask) |
|
197 |
|
198 virtual bool |
|
199 RunTask(JSContext* aCx) = 0; |
|
200 }; |
|
201 |
|
202 class WorkerCrossThreadDispatcher |
|
203 { |
|
204 friend class WorkerPrivate; |
|
205 |
|
206 // Must be acquired *before* the WorkerPrivate's mutex, when they're both |
|
207 // held. |
|
208 Mutex mMutex; |
|
209 WorkerPrivate* mWorkerPrivate; |
|
210 |
|
211 private: |
|
212 // Only created by WorkerPrivate. |
|
213 WorkerCrossThreadDispatcher(WorkerPrivate* aWorkerPrivate); |
|
214 |
|
215 // Only called by WorkerPrivate. |
|
216 void |
|
217 Forget() |
|
218 { |
|
219 MutexAutoLock lock(mMutex); |
|
220 mWorkerPrivate = nullptr; |
|
221 } |
|
222 |
|
223 public: |
|
224 NS_INLINE_DECL_THREADSAFE_REFCOUNTING(WorkerCrossThreadDispatcher) |
|
225 |
|
226 // Generically useful function for running a bit of C++ code on the worker |
|
227 // thread. |
|
228 bool |
|
229 PostTask(WorkerTask* aTask); |
|
230 }; |
|
231 |
|
232 WorkerCrossThreadDispatcher* |
|
233 GetWorkerCrossThreadDispatcher(JSContext* aCx, jsval aWorker); |
|
234 |
|
235 // Random unique constant to facilitate JSPrincipal debugging |
|
236 const uint32_t kJSPrincipalsDebugToken = 0x7e2df9d2; |
|
237 |
|
238 namespace exceptions { |
|
239 |
|
240 // Implemented in Exceptions.cpp |
|
241 void |
|
242 ThrowDOMExceptionForNSResult(JSContext* aCx, nsresult aNSResult); |
|
243 |
|
244 } // namespace exceptions |
|
245 |
|
246 // Throws the JSMSG_GETTER_ONLY exception. This shouldn't be used going |
|
247 // forward -- getter-only properties should just use JS_PSG for the setter |
|
248 // (implying no setter at all), which will not throw when set in non-strict |
|
249 // code but will in strict code. Old code should use this only for temporary |
|
250 // compatibility reasons. |
|
251 extern bool |
|
252 GetterOnlyJSNative(JSContext* aCx, unsigned aArgc, JS::Value* aVp); |
|
253 |
|
254 END_WORKERS_NAMESPACE |
|
255 |
|
256 #endif // mozilla_dom_workers_workers_h__ |