Line data Source code
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/. */
6 :
7 : #ifndef mozilla_JavascriptTimelineMarker_h_
8 : #define mozilla_JavascriptTimelineMarker_h_
9 :
10 : #include "TimelineMarker.h"
11 : #include "mozilla/dom/ProfileTimelineMarkerBinding.h"
12 : #include "mozilla/dom/RootedDictionary.h"
13 : #include "mozilla/dom/ToJSValue.h"
14 :
15 : namespace mozilla {
16 :
17 0 : class JavascriptTimelineMarker : public TimelineMarker
18 : {
19 : public:
20 : // The caller owns |aAsyncCause| here, so we must copy it into a separate
21 : // string for use later on.
22 0 : JavascriptTimelineMarker(const char* aReason,
23 : const char16_t* aFunctionName,
24 : const char16_t* aFileName,
25 : uint32_t aLineNumber,
26 : MarkerTracingType aTracingType,
27 : JS::Handle<JS::Value> aAsyncStack,
28 : const char* aAsyncCause)
29 0 : : TimelineMarker("Javascript", aTracingType, MarkerStackRequest::NO_STACK)
30 0 : , mCause(NS_ConvertUTF8toUTF16(aReason))
31 : , mFunctionName(aFunctionName)
32 : , mFileName(aFileName)
33 : , mLineNumber(aLineNumber)
34 0 : , mAsyncCause(aAsyncCause)
35 : {
36 0 : JSContext* ctx = nsContentUtils::GetCurrentJSContext();
37 0 : if (ctx) {
38 0 : mAsyncStack.init(ctx, aAsyncStack);
39 : }
40 0 : }
41 :
42 0 : virtual void AddDetails(JSContext* aCx, dom::ProfileTimelineMarker& aMarker) override
43 : {
44 0 : TimelineMarker::AddDetails(aCx, aMarker);
45 :
46 0 : aMarker.mCauseName.Construct(mCause);
47 :
48 0 : if (!mFunctionName.IsEmpty() || !mFileName.IsEmpty()) {
49 0 : dom::RootedDictionary<dom::ProfileTimelineStackFrame> stackFrame(aCx);
50 0 : stackFrame.mLine.Construct(mLineNumber);
51 0 : stackFrame.mSource.Construct(mFileName);
52 0 : stackFrame.mFunctionDisplayName.Construct(mFunctionName);
53 :
54 0 : if (mAsyncStack.isObject() && !mAsyncStack.isNullOrUndefined() &&
55 0 : !mAsyncCause.IsEmpty()) {
56 0 : JS::Rooted<JSObject*> asyncStack(aCx, mAsyncStack.toObjectOrNull());
57 0 : JS::Rooted<JSObject*> parentFrame(aCx);
58 0 : JS::Rooted<JSString*> asyncCause(aCx, JS_NewUCStringCopyN(aCx, mAsyncCause.BeginReading(),
59 0 : mAsyncCause.Length()));
60 0 : if (!asyncCause) {
61 0 : JS_ClearPendingException(aCx);
62 0 : return;
63 : }
64 :
65 0 : if (JS::IsSavedFrame(asyncStack) &&
66 0 : !JS::CopyAsyncStack(aCx, asyncStack, asyncCause, &parentFrame, 0)) {
67 0 : JS_ClearPendingException(aCx);
68 : } else {
69 0 : stackFrame.mAsyncParent = parentFrame;
70 : }
71 : }
72 :
73 0 : JS::Rooted<JS::Value> newStack(aCx);
74 0 : if (ToJSValue(aCx, stackFrame, &newStack)) {
75 0 : if (newStack.isObject()) {
76 0 : aMarker.mStack = &newStack.toObject();
77 : }
78 : } else {
79 0 : JS_ClearPendingException(aCx);
80 : }
81 : }
82 : }
83 :
84 : private:
85 : nsString mCause;
86 : nsString mFunctionName;
87 : nsString mFileName;
88 : uint32_t mLineNumber;
89 : JS::PersistentRooted<JS::Value> mAsyncStack;
90 : NS_ConvertUTF8toUTF16 mAsyncCause;
91 : };
92 :
93 : } // namespace mozilla
94 :
95 : #endif // mozilla_JavascriptTimelineMarker_h_
|