|
10 | 10 | #include <react/renderer/core/EventLogger.h>
|
11 | 11 | #include "NativePerformanceObserver.h"
|
12 | 12 |
|
13 |
| -#include <algorithm> |
| 13 | +#include <unordered_map> |
14 | 14 |
|
15 | 15 | // All the unflushed entries beyond this amount will get discarded, with
|
16 | 16 | // the amount of discarded ones sent back to the observers' callbacks as
|
@@ -167,14 +167,14 @@ double PerformanceEntryReporter::getMarkTime(
|
167 | 167 | }
|
168 | 168 |
|
169 | 169 | void PerformanceEntryReporter::event(
|
170 |
| - const std::string &name, |
| 170 | + std::string name, |
171 | 171 | double startTime,
|
172 | 172 | double duration,
|
173 | 173 | double processingStart,
|
174 | 174 | double processingEnd,
|
175 | 175 | uint32_t interactionId) {
|
176 | 176 | logEntry(
|
177 |
| - {name, |
| 177 | + {std::move(name), |
178 | 178 | static_cast<int>(PerformanceEntryType::EVENT),
|
179 | 179 | startTime,
|
180 | 180 | duration,
|
@@ -203,31 +203,89 @@ void PerformanceEntryReporter::scheduleFlushBuffer() {
|
203 | 203 | }
|
204 | 204 | }
|
205 | 205 |
|
206 |
| -static bool isDiscreteEvent(const char *name) { |
207 |
| - return !std::strstr(name, "Move") && !std::strstr(name, "Layout"); |
208 |
| -} |
| 206 | +struct StrKey { |
| 207 | + uint32_t key; |
| 208 | + constexpr StrKey(const char *s) |
| 209 | + : key(folly::hash::fnv32_buf(s, std::strlen(s))) {} |
| 210 | + |
| 211 | + constexpr bool operator==(const StrKey &rhs) const { |
| 212 | + return key == rhs.key; |
| 213 | + } |
| 214 | +}; |
| 215 | + |
| 216 | +struct StrKeyHash { |
| 217 | + constexpr size_t operator()(const StrKey &strKey) const { |
| 218 | + return static_cast<size_t>(strKey.key); |
| 219 | + } |
| 220 | +}; |
| 221 | + |
| 222 | +// Supported events for reporting, see |
| 223 | +// https://www.w3.org/TR/event-timing/#sec-events-exposed |
| 224 | +// Not all of these are currently supported by RN, but we map them anyway for |
| 225 | +// future-proofing. |
| 226 | +static const std::unordered_map<StrKey, const char *, StrKeyHash> |
| 227 | + SUPPORTED_EVENTS = { |
| 228 | + {"topAuxClick", "auxclick"}, |
| 229 | + {"topClick", "click"}, |
| 230 | + {"topContextMenu", "contextmenu"}, |
| 231 | + {"topDblClick", "dblclick"}, |
| 232 | + {"topMouseDown", "mousedown"}, |
| 233 | + {"topMouseEnter", "mouseenter"}, |
| 234 | + {"topMouseLeave", "mouseleave"}, |
| 235 | + {"topMouseOut", "mouseout"}, |
| 236 | + {"topMouseOver", "mouseover"}, |
| 237 | + {"topMouseUp", "mouseup"}, |
| 238 | + {"topPointerOver", "pointerover"}, |
| 239 | + {"topPointerEnter", "pointerenter"}, |
| 240 | + {"topPointerDown", "pointerdown"}, |
| 241 | + {"topPointerUp", "pointerup"}, |
| 242 | + {"topPointerCancel", "pointercancel"}, |
| 243 | + {"topPointerOut", "pointerout"}, |
| 244 | + {"topPointerLeave", "pointerleave"}, |
| 245 | + {"topGotPointerCapture", "gotpointercapture"}, |
| 246 | + {"topLostPointerCapture", "lostpointercapture"}, |
| 247 | + {"topTouchStart", "touchstart"}, |
| 248 | + {"topTouchEnd", "touchend"}, |
| 249 | + {"topTouchCancel", "touchcancel"}, |
| 250 | + {"topKeyDown", "keydown"}, |
| 251 | + {"topKeyPress", "keypress"}, |
| 252 | + {"topKeyUp", "keyup"}, |
| 253 | + {"topBeforeInput", "beforeinput"}, |
| 254 | + {"topInput", "input"}, |
| 255 | + {"topCompositionStart", "compositionstart"}, |
| 256 | + {"topCompositionUpdate", "compositionupdate"}, |
| 257 | + {"topCompositionEnd", "compositionend"}, |
| 258 | + {"topDragStart", "dragstart"}, |
| 259 | + {"topDragEnd", "dragend"}, |
| 260 | + {"topDragEnter", "dragenter"}, |
| 261 | + {"topDragLeave", "dragleave"}, |
| 262 | + {"topDragOver", "dragover"}, |
| 263 | + {"topDrop", "drop"}, |
| 264 | +}; |
209 | 265 |
|
210 | 266 | EventTag PerformanceEntryReporter::onEventStart(const char *name) {
|
211 |
| - if (!isReportingEvents() || !isDiscreteEvent(name)) { |
| 267 | + if (!isReportingEvents()) { |
212 | 268 | return 0;
|
213 | 269 | }
|
214 | 270 |
|
| 271 | + auto it = SUPPORTED_EVENTS.find(name); |
| 272 | + if (it == SUPPORTED_EVENTS.end()) { |
| 273 | + return 0; |
| 274 | + } |
| 275 | + |
| 276 | + const char *reportedName = it->second; |
| 277 | + |
215 | 278 | sCurrentEventTag_++;
|
216 | 279 | if (sCurrentEventTag_ == 0) {
|
217 | 280 | // The tag wrapped around (which is highly unlikely, but still)
|
218 | 281 | sCurrentEventTag_ = 1;
|
219 | 282 | }
|
220 | 283 |
|
221 |
| - if (std::strstr(name, "top") == name) { |
222 |
| - // Skip the "top" prefix if present |
223 |
| - name += 3; |
224 |
| - } |
225 |
| - |
226 | 284 | auto timeStamp = JSExecutor::performanceNow();
|
227 | 285 | {
|
228 | 286 | std::lock_guard<std::mutex> lock(eventsInFlightMutex_);
|
229 |
| - eventsInFlight_.emplace( |
230 |
| - std::make_pair(sCurrentEventTag_, EventEntry{name, timeStamp, 0.0})); |
| 287 | + eventsInFlight_.emplace(std::make_pair( |
| 288 | + sCurrentEventTag_, EventEntry{reportedName, timeStamp, 0.0})); |
231 | 289 | }
|
232 | 290 | return sCurrentEventTag_;
|
233 | 291 | }
|
@@ -259,13 +317,12 @@ void PerformanceEntryReporter::onEventEnd(EventTag tag) {
|
259 | 317 | }
|
260 | 318 | auto &entry = it->second;
|
261 | 319 | auto &name = entry.name;
|
262 |
| - std::transform(name.begin(), name.end(), name.begin(), ::tolower); |
263 | 320 |
|
264 | 321 | // TODO: Define the way to assign interaction IDs to the event chains
|
265 | 322 | // (T141358175)
|
266 | 323 | const uint32_t interactionId = 0;
|
267 | 324 | event(
|
268 |
| - std::move(name), |
| 325 | + name, |
269 | 326 | entry.startTime,
|
270 | 327 | timeStamp - entry.startTime,
|
271 | 328 | entry.dispatchTime,
|
|
0 commit comments