|
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ |
|
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 |
|
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
|
5 #ifndef nsJSEnvironment_h |
|
6 #define nsJSEnvironment_h |
|
7 |
|
8 #include "nsIScriptContext.h" |
|
9 #include "nsIScriptGlobalObject.h" |
|
10 #include "nsCOMPtr.h" |
|
11 #include "nsIObserver.h" |
|
12 #include "prtime.h" |
|
13 #include "nsCycleCollectionParticipant.h" |
|
14 #include "nsIXPConnect.h" |
|
15 #include "nsIArray.h" |
|
16 #include "mozilla/Attributes.h" |
|
17 #include "nsThreadUtils.h" |
|
18 |
|
19 class nsICycleCollectorListener; |
|
20 class nsIXPConnectJSObjectHolder; |
|
21 class nsScriptNameSpaceManager; |
|
22 class nsCycleCollectionNoteRootCallback; |
|
23 |
|
24 namespace JS { |
|
25 class AutoValueVector; |
|
26 } |
|
27 |
|
28 namespace mozilla { |
|
29 template <class> class Maybe; |
|
30 struct CycleCollectorResults; |
|
31 } |
|
32 |
|
33 // The amount of time we wait between a request to GC (due to leaving |
|
34 // a page) and doing the actual GC. |
|
35 #define NS_GC_DELAY 4000 // ms |
|
36 |
|
37 class nsJSContext : public nsIScriptContext |
|
38 { |
|
39 public: |
|
40 nsJSContext(bool aGCOnDestruction, nsIScriptGlobalObject* aGlobalObject); |
|
41 virtual ~nsJSContext(); |
|
42 |
|
43 NS_DECL_CYCLE_COLLECTING_ISUPPORTS |
|
44 NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_AMBIGUOUS(nsJSContext, |
|
45 nsIScriptContext) |
|
46 |
|
47 virtual nsIScriptGlobalObject *GetGlobalObject() MOZ_OVERRIDE; |
|
48 inline nsIScriptGlobalObject *GetGlobalObjectRef() { return mGlobalObjectRef; } |
|
49 |
|
50 virtual JSContext* GetNativeContext() MOZ_OVERRIDE; |
|
51 virtual nsresult InitContext() MOZ_OVERRIDE; |
|
52 virtual bool IsContextInitialized() MOZ_OVERRIDE; |
|
53 |
|
54 virtual nsresult SetProperty(JS::Handle<JSObject*> aTarget, const char* aPropName, nsISupports* aVal) MOZ_OVERRIDE; |
|
55 |
|
56 virtual bool GetProcessingScriptTag() MOZ_OVERRIDE; |
|
57 virtual void SetProcessingScriptTag(bool aResult) MOZ_OVERRIDE; |
|
58 |
|
59 virtual nsresult InitClasses(JS::Handle<JSObject*> aGlobalObj) MOZ_OVERRIDE; |
|
60 |
|
61 virtual void WillInitializeContext() MOZ_OVERRIDE; |
|
62 virtual void DidInitializeContext() MOZ_OVERRIDE; |
|
63 |
|
64 virtual void SetWindowProxy(JS::Handle<JSObject*> aWindowProxy) MOZ_OVERRIDE; |
|
65 virtual JSObject* GetWindowProxy() MOZ_OVERRIDE; |
|
66 virtual JSObject* GetWindowProxyPreserveColor() MOZ_OVERRIDE; |
|
67 |
|
68 static void LoadStart(); |
|
69 static void LoadEnd(); |
|
70 |
|
71 enum IsCompartment { |
|
72 CompartmentGC, |
|
73 NonCompartmentGC |
|
74 }; |
|
75 |
|
76 enum IsShrinking { |
|
77 ShrinkingGC, |
|
78 NonShrinkingGC |
|
79 }; |
|
80 |
|
81 enum IsIncremental { |
|
82 IncrementalGC, |
|
83 NonIncrementalGC |
|
84 }; |
|
85 |
|
86 // Setup all the statics etc - safe to call multiple times after Startup(). |
|
87 void EnsureStatics(); |
|
88 |
|
89 static void GarbageCollectNow(JS::gcreason::Reason reason, |
|
90 IsIncremental aIncremental = NonIncrementalGC, |
|
91 IsCompartment aCompartment = NonCompartmentGC, |
|
92 IsShrinking aShrinking = NonShrinkingGC, |
|
93 int64_t aSliceMillis = 0); |
|
94 static void ShrinkGCBuffersNow(); |
|
95 |
|
96 // If aExtraForgetSkippableCalls is -1, forgetSkippable won't be |
|
97 // called even if the previous collection was GC. |
|
98 static void CycleCollectNow(nsICycleCollectorListener *aListener = nullptr, |
|
99 int32_t aExtraForgetSkippableCalls = 0); |
|
100 |
|
101 // Run a cycle collector slice, using a heuristic to decide how long to run it. |
|
102 static void RunCycleCollectorSlice(); |
|
103 |
|
104 static void BeginCycleCollectionCallback(); |
|
105 static void EndCycleCollectionCallback(mozilla::CycleCollectorResults &aResults); |
|
106 |
|
107 static void RunNextCollectorTimer(); |
|
108 |
|
109 static void PokeGC(JS::gcreason::Reason aReason, int aDelay = 0); |
|
110 static void KillGCTimer(); |
|
111 |
|
112 static void PokeShrinkGCBuffers(); |
|
113 static void KillShrinkGCBuffersTimer(); |
|
114 |
|
115 static void MaybePokeCC(); |
|
116 static void KillCCTimer(); |
|
117 static void KillICCTimer(); |
|
118 static void KillFullGCTimer(); |
|
119 static void KillInterSliceGCTimer(); |
|
120 |
|
121 // Calling LikelyShortLivingObjectCreated() makes a GC more likely. |
|
122 static void LikelyShortLivingObjectCreated(); |
|
123 |
|
124 virtual void GC(JS::gcreason::Reason aReason) MOZ_OVERRIDE; |
|
125 |
|
126 static uint32_t CleanupsSinceLastGC(); |
|
127 |
|
128 nsIScriptGlobalObject* GetCachedGlobalObject() |
|
129 { |
|
130 // Verify that we have a global so that this |
|
131 // does always return a null when GetGlobalObject() is null. |
|
132 JSObject* global = GetWindowProxy(); |
|
133 return global ? mGlobalObjectRef.get() : nullptr; |
|
134 } |
|
135 protected: |
|
136 nsresult InitializeExternalClasses(); |
|
137 |
|
138 // Helper to convert xpcom datatypes to jsvals. |
|
139 nsresult ConvertSupportsTojsvals(nsISupports *aArgs, |
|
140 JS::Handle<JSObject*> aScope, |
|
141 JS::AutoValueVector &aArgsOut); |
|
142 |
|
143 nsresult AddSupportsPrimitiveTojsvals(nsISupports *aArg, JS::Value *aArgv); |
|
144 |
|
145 // Report the pending exception on our mContext, if any. This |
|
146 // function will set aside the frame chain on mContext before |
|
147 // reporting. |
|
148 void ReportPendingException(); |
|
149 |
|
150 private: |
|
151 void DestroyJSContext(); |
|
152 |
|
153 nsrefcnt GetCCRefcnt(); |
|
154 |
|
155 JSContext *mContext; |
|
156 JS::Heap<JSObject*> mWindowProxy; |
|
157 |
|
158 bool mIsInitialized; |
|
159 bool mGCOnDestruction; |
|
160 bool mProcessingScriptTag; |
|
161 |
|
162 PRTime mModalStateTime; |
|
163 uint32_t mModalStateDepth; |
|
164 |
|
165 // mGlobalObjectRef ensures that the outer window stays alive as long as the |
|
166 // context does. It is eventually collected by the cycle collector. |
|
167 nsCOMPtr<nsIScriptGlobalObject> mGlobalObjectRef; |
|
168 |
|
169 static void JSOptionChangedCallback(const char *pref, void *data); |
|
170 |
|
171 static bool DOMOperationCallback(JSContext *cx); |
|
172 }; |
|
173 |
|
174 class nsIJSRuntimeService; |
|
175 class nsIPrincipal; |
|
176 class nsPIDOMWindow; |
|
177 |
|
178 namespace mozilla { |
|
179 namespace dom { |
|
180 |
|
181 void StartupJSEnvironment(); |
|
182 void ShutdownJSEnvironment(); |
|
183 |
|
184 // Get the NameSpaceManager, creating if necessary |
|
185 nsScriptNameSpaceManager* GetNameSpaceManager(); |
|
186 |
|
187 // Runnable that's used to do async error reporting |
|
188 class AsyncErrorReporter : public nsRunnable |
|
189 { |
|
190 public: |
|
191 // aWindow may be null if this error report is not associated with a window |
|
192 AsyncErrorReporter(JSRuntime* aRuntime, |
|
193 JSErrorReport* aErrorReport, |
|
194 const char* aFallbackMessage, |
|
195 bool aIsChromeError, // To determine category |
|
196 nsPIDOMWindow* aWindow); |
|
197 |
|
198 NS_IMETHOD Run() |
|
199 { |
|
200 ReportError(); |
|
201 return NS_OK; |
|
202 } |
|
203 |
|
204 protected: |
|
205 // Do the actual error reporting |
|
206 void ReportError(); |
|
207 |
|
208 nsString mErrorMsg; |
|
209 nsString mFileName; |
|
210 nsString mSourceLine; |
|
211 nsCString mCategory; |
|
212 uint32_t mLineNumber; |
|
213 uint32_t mColumn; |
|
214 uint32_t mFlags; |
|
215 uint64_t mInnerWindowID; |
|
216 }; |
|
217 |
|
218 } // namespace dom |
|
219 } // namespace mozilla |
|
220 |
|
221 // An interface for fast and native conversion to/from nsIArray. If an object |
|
222 // supports this interface, JS can reach directly in for the argv, and avoid |
|
223 // nsISupports conversion. If this interface is not supported, the object will |
|
224 // be queried for nsIArray, and everything converted via xpcom objects. |
|
225 #define NS_IJSARGARRAY_IID \ |
|
226 { 0xb6acdac8, 0xf5c6, 0x432c, \ |
|
227 { 0xa8, 0x6e, 0x33, 0xee, 0xb1, 0xb0, 0xcd, 0xdc } } |
|
228 |
|
229 class nsIJSArgArray : public nsIArray |
|
230 { |
|
231 public: |
|
232 NS_DECLARE_STATIC_IID_ACCESSOR(NS_IJSARGARRAY_IID) |
|
233 // Bug 312003 describes why this must be "void **", but after calling argv |
|
234 // may be cast to JS::Value* and the args found at: |
|
235 // ((JS::Value*)argv)[0], ..., ((JS::Value*)argv)[argc - 1] |
|
236 virtual nsresult GetArgs(uint32_t *argc, void **argv) = 0; |
|
237 }; |
|
238 |
|
239 NS_DEFINE_STATIC_IID_ACCESSOR(nsIJSArgArray, NS_IJSARGARRAY_IID) |
|
240 |
|
241 /* prototypes */ |
|
242 void NS_ScriptErrorReporter(JSContext *cx, const char *message, JSErrorReport *report); |
|
243 |
|
244 JSObject* NS_DOMReadStructuredClone(JSContext* cx, |
|
245 JSStructuredCloneReader* reader, uint32_t tag, |
|
246 uint32_t data, void* closure); |
|
247 |
|
248 bool NS_DOMWriteStructuredClone(JSContext* cx, |
|
249 JSStructuredCloneWriter* writer, |
|
250 JS::Handle<JSObject*> obj, void *closure); |
|
251 |
|
252 void NS_DOMStructuredCloneError(JSContext* cx, uint32_t errorid); |
|
253 |
|
254 #endif /* nsJSEnvironment_h */ |