Backed out changeset 2450366cf7ca (bug 1891629) for causing win msix mochitest failures
[gecko.git] / dom / console / Console.h
blob5898c6b0f54ab6f4de4ae58d765f5dff322069d0
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 #ifndef mozilla_dom_Console_h
8 #define mozilla_dom_Console_h
10 #include "domstubs.h"
11 #include "mozilla/dom/ConsoleBinding.h"
12 #include "mozilla/dom/ConsoleInstanceBinding.h"
13 #include "mozilla/TimeStamp.h"
14 #include "nsCycleCollectionParticipant.h"
15 #include "nsTHashMap.h"
16 #include "nsHashKeys.h"
17 #include "nsIObserver.h"
18 #include "nsWeakReference.h"
20 class nsIConsoleAPIStorage;
21 class nsIGlobalObject;
22 class nsPIDOMWindowInner;
23 class nsIStackFrame;
25 namespace mozilla::dom {
27 class AnyCallback;
28 class ConsoleCallData;
29 class ConsoleInstance;
30 class ConsoleRunnable;
31 class ConsoleCallDataRunnable;
32 class ConsoleProfileRunnable;
33 class MainThreadConsoleData;
35 class Console final : public nsIObserver, public nsSupportsWeakReference {
36 public:
37 NS_DECL_CYCLE_COLLECTING_ISUPPORTS
38 NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_AMBIGUOUS(Console, nsIObserver)
39 NS_DECL_NSIOBSERVER
41 static already_AddRefed<Console> Create(JSContext* aCx,
42 nsPIDOMWindowInner* aWindow,
43 ErrorResult& aRv);
45 static already_AddRefed<Console> CreateForWorklet(JSContext* aCx,
46 nsIGlobalObject* aGlobal,
47 uint64_t aOuterWindowID,
48 uint64_t aInnerWindowID,
49 ErrorResult& aRv);
51 MOZ_CAN_RUN_SCRIPT
52 static void Log(const GlobalObject& aGlobal,
53 const Sequence<JS::Value>& aData);
55 MOZ_CAN_RUN_SCRIPT
56 static void Info(const GlobalObject& aGlobal,
57 const Sequence<JS::Value>& aData);
59 MOZ_CAN_RUN_SCRIPT
60 static void Warn(const GlobalObject& aGlobal,
61 const Sequence<JS::Value>& aData);
63 MOZ_CAN_RUN_SCRIPT
64 static void Error(const GlobalObject& aGlobal,
65 const Sequence<JS::Value>& aData);
67 MOZ_CAN_RUN_SCRIPT
68 static void Exception(const GlobalObject& aGlobal,
69 const Sequence<JS::Value>& aData);
71 MOZ_CAN_RUN_SCRIPT
72 static void Debug(const GlobalObject& aGlobal,
73 const Sequence<JS::Value>& aData);
75 MOZ_CAN_RUN_SCRIPT
76 static void Table(const GlobalObject& aGlobal,
77 const Sequence<JS::Value>& aData);
79 MOZ_CAN_RUN_SCRIPT
80 static void Trace(const GlobalObject& aGlobal,
81 const Sequence<JS::Value>& aData);
83 MOZ_CAN_RUN_SCRIPT
84 static void Dir(const GlobalObject& aGlobal,
85 const Sequence<JS::Value>& aData);
87 MOZ_CAN_RUN_SCRIPT
88 static void Dirxml(const GlobalObject& aGlobal,
89 const Sequence<JS::Value>& aData);
91 MOZ_CAN_RUN_SCRIPT
92 static void Group(const GlobalObject& aGlobal,
93 const Sequence<JS::Value>& aData);
95 MOZ_CAN_RUN_SCRIPT
96 static void GroupCollapsed(const GlobalObject& aGlobal,
97 const Sequence<JS::Value>& aData);
99 MOZ_CAN_RUN_SCRIPT
100 static void GroupEnd(const GlobalObject& aGlobal);
102 MOZ_CAN_RUN_SCRIPT
103 static void Time(const GlobalObject& aGlobal, const nsAString& aLabel);
105 MOZ_CAN_RUN_SCRIPT
106 static void TimeLog(const GlobalObject& aGlobal, const nsAString& aLabel,
107 const Sequence<JS::Value>& aData);
109 MOZ_CAN_RUN_SCRIPT
110 static void TimeEnd(const GlobalObject& aGlobal, const nsAString& aLabel);
112 MOZ_CAN_RUN_SCRIPT
113 static void TimeStamp(const GlobalObject& aGlobal,
114 const JS::Handle<JS::Value> aData);
116 MOZ_CAN_RUN_SCRIPT
117 static void Profile(const GlobalObject& aGlobal,
118 const Sequence<JS::Value>& aData);
120 MOZ_CAN_RUN_SCRIPT
121 static void ProfileEnd(const GlobalObject& aGlobal,
122 const Sequence<JS::Value>& aData);
124 MOZ_CAN_RUN_SCRIPT
125 static void Assert(const GlobalObject& aGlobal, bool aCondition,
126 const Sequence<JS::Value>& aData);
128 MOZ_CAN_RUN_SCRIPT
129 static void Count(const GlobalObject& aGlobal, const nsAString& aLabel);
131 MOZ_CAN_RUN_SCRIPT
132 static void CountReset(const GlobalObject& aGlobal, const nsAString& aLabel);
134 MOZ_CAN_RUN_SCRIPT
135 static void Clear(const GlobalObject& aGlobal);
137 static already_AddRefed<ConsoleInstance> CreateInstance(
138 const GlobalObject& aGlobal, const ConsoleInstanceOptions& aOptions);
140 void ClearStorage();
142 void RetrieveConsoleEvents(JSContext* aCx, nsTArray<JS::Value>& aEvents,
143 ErrorResult& aRv);
145 void SetConsoleEventHandler(AnyCallback* aHandler);
147 private:
148 Console(JSContext* aCx, nsIGlobalObject* aGlobal, uint64_t aOuterWindowID,
149 uint64_t aInnerWIndowID);
150 ~Console();
152 void Initialize(ErrorResult& aRv);
154 void Shutdown();
156 enum MethodName {
157 MethodLog,
158 MethodInfo,
159 MethodWarn,
160 MethodError,
161 MethodException,
162 MethodDebug,
163 MethodTable,
164 MethodTrace,
165 MethodDir,
166 MethodDirxml,
167 MethodGroup,
168 MethodGroupCollapsed,
169 MethodGroupEnd,
170 MethodTime,
171 MethodTimeLog,
172 MethodTimeEnd,
173 MethodTimeStamp,
174 MethodAssert,
175 MethodCount,
176 MethodCountReset,
177 MethodClear,
178 MethodProfile,
179 MethodProfileEnd,
182 static already_AddRefed<Console> GetConsole(const GlobalObject& aGlobal);
184 static already_AddRefed<Console> GetConsoleInternal(
185 const GlobalObject& aGlobal, ErrorResult& aRv);
187 MOZ_CAN_RUN_SCRIPT
188 static void ProfileMethod(const GlobalObject& aGlobal, MethodName aName,
189 const nsAString& aAction,
190 const Sequence<JS::Value>& aData);
192 MOZ_CAN_RUN_SCRIPT
193 void ProfileMethodInternal(JSContext* aCx, MethodName aName,
194 const nsAString& aAction,
195 const Sequence<JS::Value>& aData);
197 // Implementation of the mainthread-only parts of ProfileMethod.
198 // This is indepedent of console instance state.
199 static void ProfileMethodMainthread(JSContext* aCx, const nsAString& aAction,
200 const Sequence<JS::Value>& aData);
202 MOZ_CAN_RUN_SCRIPT
203 static void Method(const GlobalObject& aGlobal, MethodName aName,
204 const nsAString& aString,
205 const Sequence<JS::Value>& aData);
207 MOZ_CAN_RUN_SCRIPT
208 void MethodInternal(JSContext* aCx, MethodName aName,
209 const nsAString& aString,
210 const Sequence<JS::Value>& aData);
212 MOZ_CAN_RUN_SCRIPT
213 static void StringMethod(const GlobalObject& aGlobal, const nsAString& aLabel,
214 const Sequence<JS::Value>& aData,
215 MethodName aMethodName,
216 const nsAString& aMethodString);
218 MOZ_CAN_RUN_SCRIPT
219 void StringMethodInternal(JSContext* aCx, const nsAString& aLabel,
220 const Sequence<JS::Value>& aData,
221 MethodName aMethodName,
222 const nsAString& aMethodString);
224 MainThreadConsoleData* GetOrCreateMainThreadData();
226 // Returns true on success; otherwise false.
227 bool StoreCallData(JSContext* aCx, ConsoleCallData* aCallData,
228 const Sequence<JS::Value>& aArguments);
230 void UnstoreCallData(ConsoleCallData* aData);
232 // aCx and aArguments must be in the same JS compartment.
233 MOZ_CAN_RUN_SCRIPT
234 void NotifyHandler(JSContext* aCx, const Sequence<JS::Value>& aArguments,
235 ConsoleCallData* aData);
237 // PopulateConsoleNotificationInTheTargetScope receives aCx and aArguments in
238 // the same JS compartment and populates the ConsoleEvent object
239 // (aEventValue) in the aTargetScope.
240 // aTargetScope can be:
241 // - the system-principal scope when we want to dispatch the ConsoleEvent to
242 // nsIConsoleAPIStorage (See the comment in Console.cpp about the use of
243 // xpc::PrivilegedJunkScope()
244 // - the mConsoleEventNotifier->CallableGlobal() when we want to notify this
245 // handler about a new ConsoleEvent.
246 // - It can be the global from the JSContext when RetrieveConsoleEvents is
247 // called.
248 static bool PopulateConsoleNotificationInTheTargetScope(
249 JSContext* aCx, const Sequence<JS::Value>& aArguments,
250 JS::Handle<JSObject*> aTargetScope,
251 JS::MutableHandle<JS::Value> aEventValue, ConsoleCallData* aData,
252 nsTArray<nsString>* aGroupStack);
254 enum TimerStatus {
255 eTimerUnknown,
256 eTimerDone,
257 eTimerAlreadyExists,
258 eTimerDoesntExist,
259 eTimerJSException,
260 eTimerMaxReached,
263 static JS::Value CreateTimerError(JSContext* aCx, const nsAString& aLabel,
264 TimerStatus aStatus);
266 // StartTimer is called on the owning thread and populates aTimerLabel and
267 // aTimerValue.
268 // * aCx - the JSContext rooting aName.
269 // * aName - this is (should be) the name of the timer as JS::Value.
270 // * aTimestamp - the monotonicTimer for this context taken from
271 // performance.now().
272 // * aTimerLabel - This label will be populated with the aName converted to a
273 // string.
274 // * aTimerValue - the StartTimer value stored into (or taken from)
275 // mTimerRegistry.
276 TimerStatus StartTimer(JSContext* aCx, const JS::Value& aName,
277 DOMHighResTimeStamp aTimestamp, nsAString& aTimerLabel,
278 DOMHighResTimeStamp* aTimerValue);
280 // CreateStartTimerValue generates a ConsoleTimerStart dictionary exposed as
281 // JS::Value. If aTimerStatus is false, it generates a ConsoleTimerError
282 // instead. It's called only after the execution StartTimer on the owning
283 // thread.
284 // * aCx - this is the context that will root the returned value.
285 // * aTimerLabel - this label must be what StartTimer received as aTimerLabel.
286 // * aTimerStatus - the return value of StartTimer.
287 static JS::Value CreateStartTimerValue(JSContext* aCx,
288 const nsAString& aTimerLabel,
289 TimerStatus aTimerStatus);
291 // LogTimer follows the same pattern as StartTimer: it runs on the
292 // owning thread and populates aTimerLabel and aTimerDuration, used by
293 // CreateLogOrEndTimerValue.
294 // * aCx - the JSContext rooting aName.
295 // * aName - this is (should be) the name of the timer as JS::Value.
296 // * aTimestamp - the monotonicTimer for this context taken from
297 // performance.now().
298 // * aTimerLabel - This label will be populated with the aName converted to a
299 // string.
300 // * aTimerDuration - the difference between aTimestamp and when the timer
301 // started (see StartTimer).
302 // * aCancelTimer - if true, the timer is removed from the table.
303 TimerStatus LogTimer(JSContext* aCx, const JS::Value& aName,
304 DOMHighResTimeStamp aTimestamp, nsAString& aTimerLabel,
305 double* aTimerDuration, bool aCancelTimer);
307 // This method generates a ConsoleTimerEnd dictionary exposed as JS::Value, or
308 // a ConsoleTimerError dictionary if aTimerStatus is false. See LogTimer.
309 // * aCx - this is the context that will root the returned value.
310 // * aTimerLabel - this label must be what LogTimer received as aTimerLabel.
311 // * aTimerDuration - this is what LogTimer received as aTimerDuration
312 // * aTimerStatus - the return value of LogTimer.
313 static JS::Value CreateLogOrEndTimerValue(JSContext* aCx,
314 const nsAString& aLabel,
315 double aDuration,
316 TimerStatus aStatus);
318 // The method populates a Sequence from an array of JS::Value.
319 bool ArgumentsToValueList(const Sequence<JS::Value>& aData,
320 Sequence<JS::Value>& aSequence) const;
322 // This method follows the same pattern as StartTimer: its runs on the owning
323 // thread and populate aCountLabel, used by CreateCounterOrResetCounterValue.
324 // Returns 3 possible values:
325 // * MAX_PAGE_COUNTERS in case of error that has to be reported;
326 // * 0 in case of a CX exception. The operation cannot continue;
327 // * the incremented counter value.
328 // Params:
329 // * aCx - the JSContext rooting aData.
330 // * aData - the arguments received by the console.count() method.
331 // * aCountLabel - the label that will be populated by this method.
332 uint32_t IncreaseCounter(JSContext* aCx, const Sequence<JS::Value>& aData,
333 nsAString& aCountLabel);
335 // This method follows the same pattern as StartTimer: its runs on the owning
336 // thread and populate aCountLabel, used by CreateCounterResetValue. Returns
337 // 3 possible values:
338 // * MAX_PAGE_COUNTERS in case of error that has to be reported;
339 // * 0 elsewhere. In case of a CX exception, aCountLabel will be an empty
340 // string.
341 // Params:
342 // * aCx - the JSContext rooting aData.
343 // * aData - the arguments received by the console.count() method.
344 // * aCountLabel - the label that will be populated by this method.
345 uint32_t ResetCounter(JSContext* aCx, const Sequence<JS::Value>& aData,
346 nsAString& aCountLabel);
348 static bool ShouldIncludeStackTrace(MethodName aMethodName);
350 void AssertIsOnOwningThread() const;
352 bool IsShuttingDown() const;
354 bool MonotonicTimer(JSContext* aCx, MethodName aMethodName,
355 const Sequence<JS::Value>& aData,
356 DOMHighResTimeStamp* aTimeStamp);
358 void StringifyElement(Element* aElement, nsAString& aOut);
360 MOZ_CAN_RUN_SCRIPT
361 void MaybeExecuteDumpFunction(JSContext* aCx, const nsAString& aMethodName,
362 const Sequence<JS::Value>& aData,
363 nsIStackFrame* aStack);
365 MOZ_CAN_RUN_SCRIPT
366 void MaybeExecuteDumpFunctionForTime(JSContext* aCx, MethodName aMethodName,
367 const nsAString& aMethodString,
368 uint64_t aMonotonicTimer,
369 const JS::Value& aData);
371 MOZ_CAN_RUN_SCRIPT
372 void ExecuteDumpFunction(const nsAString& aMessage);
374 bool ShouldProceed(MethodName aName) const;
376 uint32_t WebIDLLogLevelToInteger(ConsoleLogLevel aLevel) const;
378 uint32_t InternalLogLevelToInteger(MethodName aName) const;
380 class ArgumentData {
381 public:
382 bool Initialize(JSContext* aCx, const Sequence<JS::Value>& aArguments);
383 void Trace(const TraceCallbacks& aCallbacks, void* aClosure);
384 bool PopulateArgumentsSequence(Sequence<JS::Value>& aSequence) const;
385 JSObject* Global() const { return mGlobal; }
387 private:
388 void AssertIsOnOwningThread() const {
389 NS_ASSERT_OWNINGTHREAD(ArgumentData);
392 NS_DECL_OWNINGTHREAD;
393 JS::Heap<JSObject*> mGlobal;
394 nsTArray<JS::Heap<JS::Value>> mArguments;
397 // Owning/CC thread only
398 nsCOMPtr<nsIGlobalObject> mGlobal;
400 // Touched on the owner thread.
401 nsTHashMap<nsStringHashKey, DOMHighResTimeStamp> mTimerRegistry;
402 nsTHashMap<nsStringHashKey, uint32_t> mCounterRegistry;
404 nsTArray<RefPtr<ConsoleCallData>> mCallDataStorage;
405 // These are references to the arguments we received in each call
406 // from the DOM bindings.
407 // Vector<T> supports non-memmovable types such as ArgumentData
408 // (without any need to jump through hoops like
409 // MOZ_DECLARE_RELOCATE_USING_MOVE_CONSTRUCTOR_FOR_TEMPLATE for nsTArray).
410 Vector<ArgumentData> mArgumentStorage;
412 RefPtr<AnyCallback> mConsoleEventNotifier;
414 RefPtr<MainThreadConsoleData> mMainThreadData;
415 // This is the stack for grouping relating to Console-thread events, when
416 // the Console thread is not the main thread.
417 nsTArray<nsString> mGroupStack;
419 uint64_t mOuterID;
420 uint64_t mInnerID;
422 // Set only by ConsoleInstance:
423 nsString mConsoleID;
424 nsString mPassedInnerID;
425 RefPtr<ConsoleInstanceDumpCallback> mDumpFunction;
426 bool mDumpToStdout;
427 nsString mPrefix;
428 bool mChromeInstance;
429 uint32_t mCurrentLogLevel;
431 enum { eUnknown, eInitialized, eShuttingDown } mStatus;
433 // This is used when Console is created and it's used only for JSM custom
434 // console instance.
435 mozilla::TimeStamp mCreationTimeStamp;
437 friend class ConsoleCallData;
438 friend class ConsoleCallDataWorkletRunnable;
439 friend class ConsoleInstance;
440 friend class ConsoleProfileWorkerRunnable;
441 friend class ConsoleProfileWorkletRunnable;
442 friend class ConsoleRunnable;
443 friend class ConsoleWorkerRunnable;
444 friend class ConsoleWorkletRunnable;
445 friend class MainThreadConsoleData;
448 } // namespace mozilla::dom
450 #endif /* mozilla_dom_Console_h */