Coverage Report

Created: 2018-09-25 14:53

/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_