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