summaryrefslogtreecommitdiffstats
path: root/gfx/layers/apz/testutil/APZTestData.cpp
blob: 4154607d75ac66bffb6287d413cf3180a23116cf (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

#include "APZTestData.h"
#include "mozilla/dom/APZTestDataBinding.h"
#include "mozilla/dom/ToJSValue.h"
#include "nsString.h"

namespace mozilla {
namespace layers {

struct APZTestDataToJSConverter {
  template <typename Key, typename Value, typename KeyValuePair>
  static void ConvertMap(const std::map<Key, Value>& aFrom,
                         dom::Sequence<KeyValuePair>& aOutTo,
                         void (*aElementConverter)(const Key&, const Value&,
                                                   KeyValuePair&)) {
    for (auto it = aFrom.begin(); it != aFrom.end(); ++it) {
      if (!aOutTo.AppendElement(fallible)) {
        // XXX(Bug 1632090) Instead of extending the array 1-by-1 (which might
        // involve multiple reallocations) and potentially crashing here,
        // SetCapacity could be called outside the loop once.
        mozalloc_handle_oom(0);
      }
      aElementConverter(it->first, it->second, aOutTo.LastElement());
    }
  }

  template <typename Src, typename Target>
  static void ConvertList(const nsTArray<Src>& aFrom,
                          dom::Sequence<Target>& aOutTo,
                          void (*aElementConverter)(const Src&, Target&)) {
    for (auto it = aFrom.begin(); it != aFrom.end(); ++it) {
      if (!aOutTo.AppendElement(fallible)) {
        // XXX(Bug 1632090) Instead of extending the array 1-by-1 (which might
        // involve multiple reallocations) and potentially crashing here,
        // SetCapacity could be called outside the loop once.
        mozalloc_handle_oom(0);
      }
      aElementConverter(*it, aOutTo.LastElement());
    }
  }

  static void ConvertAPZTestData(const APZTestData& aFrom,
                                 dom::APZTestData& aOutTo) {
    ConvertMap(aFrom.mPaints, aOutTo.mPaints.Construct(), ConvertBucket);
    ConvertMap(aFrom.mRepaintRequests, aOutTo.mRepaintRequests.Construct(),
               ConvertBucket);
    ConvertList(aFrom.mHitResults, aOutTo.mHitResults.Construct(),
                ConvertHitResult);
    ConvertList(aFrom.mSampledResults, aOutTo.mSampledResults.Construct(),
                ConvertSampledResult);
    ConvertMap(aFrom.mAdditionalData, aOutTo.mAdditionalData.Construct(),
               ConvertAdditionalDataEntry);
  }

  static void ConvertBucket(const SequenceNumber& aKey,
                            const APZTestData::Bucket& aValue,
                            dom::APZBucket& aOutKeyValuePair) {
    aOutKeyValuePair.mSequenceNumber.Construct() = aKey;
    ConvertMap(aValue, aOutKeyValuePair.mScrollFrames.Construct(),
               ConvertScrollFrameData);
  }

  static void ConvertScrollFrameData(const APZTestData::ViewID& aKey,
                                     const APZTestData::ScrollFrameData& aValue,
                                     dom::ScrollFrameData& aOutKeyValuePair) {
    aOutKeyValuePair.mScrollId.Construct() = aKey;
    ConvertMap(aValue, aOutKeyValuePair.mEntries.Construct(), ConvertEntry);
  }

  static void ConvertEntry(const std::string& aKey, const std::string& aValue,
                           dom::ScrollFrameDataEntry& aOutKeyValuePair) {
    ConvertString(aKey, aOutKeyValuePair.mKey.Construct());
    ConvertString(aValue, aOutKeyValuePair.mValue.Construct());
  }

  static void ConvertAdditionalDataEntry(
      const std::string& aKey, const std::string& aValue,
      dom::AdditionalDataEntry& aOutKeyValuePair) {
    ConvertString(aKey, aOutKeyValuePair.mKey.Construct());
    ConvertString(aValue, aOutKeyValuePair.mValue.Construct());
  }

  static void ConvertString(const std::string& aFrom, nsString& aOutTo) {
    CopyUTF8toUTF16(aFrom, aOutTo);
  }

  static void ConvertHitResult(const APZTestData::HitResult& aResult,
                               dom::APZHitResult& aOutHitResult) {
    aOutHitResult.mScreenX.Construct() = aResult.point.x;
    aOutHitResult.mScreenY.Construct() = aResult.point.y;
    static_assert(MaxEnumValue<gfx::CompositorHitTestInfo::valueType>::value <
                      std::numeric_limits<uint16_t>::digits,
                  "CompositorHitTestFlags MAX value have to be less than "
                  "number of bits in uint16_t");
    aOutHitResult.mHitResult.Construct() =
        static_cast<uint16_t>(aResult.result.serialize());
    aOutHitResult.mLayersId.Construct() = aResult.layersId.mId;
    aOutHitResult.mScrollId.Construct() = aResult.scrollId;
  }

  static void ConvertSampledResult(const APZTestData::SampledResult& aResult,
                                   dom::APZSampledResult& aOutSampledResult) {
    aOutSampledResult.mScrollOffsetX.Construct() = aResult.scrollOffset.x;
    aOutSampledResult.mScrollOffsetY.Construct() = aResult.scrollOffset.y;
    aOutSampledResult.mLayersId.Construct() = aResult.layersId.mId;
    aOutSampledResult.mScrollId.Construct() = aResult.scrollId;
    aOutSampledResult.mSampledTimeStamp.Construct() = aResult.sampledTimeStamp;
  }
};

bool APZTestData::ToJS(JS::MutableHandle<JS::Value> aOutValue,
                       JSContext* aContext) const {
  dom::APZTestData result;
  APZTestDataToJSConverter::ConvertAPZTestData(*this, result);
  return dom::ToJSValue(aContext, result, aOutValue);
}

}  // namespace layers
}  // namespace mozilla