diff --git a/packages/react-native/Libraries/__tests__/__snapshots__/public-api-test.js.snap b/packages/react-native/Libraries/__tests__/__snapshots__/public-api-test.js.snap index 2b4978f9b47..281281bf85e 100644 --- a/packages/react-native/Libraries/__tests__/__snapshots__/public-api-test.js.snap +++ b/packages/react-native/Libraries/__tests__/__snapshots__/public-api-test.js.snap @@ -9696,7 +9696,12 @@ declare export default class Performance { exports[`public API should not change unintentionally src/private/webapis/performance/PerformanceEntry.js 1`] = ` "export type DOMHighResTimeStamp = number; -export type PerformanceEntryType = \\"mark\\" | \\"measure\\" | \\"event\\" | \\"longtask\\"; +export type PerformanceEntryType = + | \\"mark\\" + | \\"measure\\" + | \\"event\\" + | \\"longtask\\" + | \\"resource\\"; export type PerformanceEntryJSON = { name: string, entryType: PerformanceEntryType, diff --git a/packages/react-native/ReactCommon/react/nativemodule/webperformance/NativePerformance.cpp b/packages/react-native/ReactCommon/react/nativemodule/webperformance/NativePerformance.cpp index 19de170d6bc..50165c3b17b 100644 --- a/packages/react-native/ReactCommon/react/nativemodule/webperformance/NativePerformance.cpp +++ b/packages/react-native/ReactCommon/react/nativemodule/webperformance/NativePerformance.cpp @@ -65,6 +65,16 @@ NativePerformanceEntry toNativePerformanceEntry(const PerformanceEntry& entry) { nativeEntry.processingEnd = eventEntry.processingEnd; nativeEntry.interactionId = eventEntry.interactionId; } + if (std::holds_alternative(entry)) { + auto resourceEntry = std::get(entry); + nativeEntry.fetchStart = resourceEntry.fetchStart; + nativeEntry.requestStart = resourceEntry.requestStart; + nativeEntry.connectStart = resourceEntry.connectStart; + nativeEntry.connectEnd = resourceEntry.connectEnd; + nativeEntry.responseStart = resourceEntry.responseStart; + nativeEntry.responseEnd = resourceEntry.responseEnd; + nativeEntry.responseStatus = resourceEntry.responseStatus; + } return nativeEntry; } diff --git a/packages/react-native/ReactCommon/react/nativemodule/webperformance/NativePerformance.h b/packages/react-native/ReactCommon/react/nativemodule/webperformance/NativePerformance.h index 1d04c4e7086..7723a1a2c81 100644 --- a/packages/react-native/ReactCommon/react/nativemodule/webperformance/NativePerformance.h +++ b/packages/react-native/ReactCommon/react/nativemodule/webperformance/NativePerformance.h @@ -61,6 +61,15 @@ struct NativePerformanceEntry { std::optional processingStart; std::optional processingEnd; std::optional interactionId; + + // For PerformanceResourceTiming only + std::optional fetchStart; + std::optional requestStart; + std::optional connectStart; + std::optional connectEnd; + std::optional responseStart; + std::optional responseEnd; + std::optional responseStatus; }; template <> diff --git a/packages/react-native/ReactCommon/react/performance/timeline/PerformanceEntry.h b/packages/react-native/ReactCommon/react/performance/timeline/PerformanceEntry.h index b9f89c08c83..45a7044934c 100644 --- a/packages/react-native/ReactCommon/react/performance/timeline/PerformanceEntry.h +++ b/packages/react-native/ReactCommon/react/performance/timeline/PerformanceEntry.h @@ -8,6 +8,7 @@ #pragma once #include +#include #include #include @@ -21,7 +22,8 @@ enum class PerformanceEntryType { MEASURE = 2, EVENT = 3, LONGTASK = 4, - _NEXT = 5, + RESOURCE = 5, + _NEXT = 6, }; struct AbstractPerformanceEntry { @@ -51,11 +53,26 @@ struct PerformanceLongTaskTiming : AbstractPerformanceEntry { PerformanceEntryType::LONGTASK; }; +struct PerformanceResourceTiming : AbstractPerformanceEntry { + static constexpr PerformanceEntryType entryType = + PerformanceEntryType::RESOURCE; + /** Aligns with `startTime`. */ + std::optional fetchStart; + std::optional requestStart; + std::optional connectStart; + std::optional connectEnd; + std::optional responseStart; + /** Aligns with `duration`. */ + std::optional responseEnd; + std::optional responseStatus; +}; + using PerformanceEntry = std::variant< PerformanceMark, PerformanceMeasure, PerformanceEventTiming, - PerformanceLongTaskTiming>; + PerformanceLongTaskTiming, + PerformanceResourceTiming>; struct PerformanceEntrySorter { bool operator()(const PerformanceEntry& lhs, const PerformanceEntry& rhs) { diff --git a/packages/react-native/ReactCommon/react/performance/timeline/PerformanceEntryReporter.h b/packages/react-native/ReactCommon/react/performance/timeline/PerformanceEntryReporter.h index 650a7ec3460..a8a75fbfcd6 100644 --- a/packages/react-native/ReactCommon/react/performance/timeline/PerformanceEntryReporter.h +++ b/packages/react-native/ReactCommon/react/performance/timeline/PerformanceEntryReporter.h @@ -109,6 +109,7 @@ class PerformanceEntryReporter { PerformanceEntryCircularBuffer longTaskBuffer_{LONG_TASK_BUFFER_SIZE}; PerformanceEntryKeyedBuffer markBuffer_; PerformanceEntryKeyedBuffer measureBuffer_; + PerformanceEntryKeyedBuffer resourceBuffer_; std::unordered_map eventCounts_; @@ -127,6 +128,8 @@ class PerformanceEntryReporter { return measureBuffer_; case PerformanceEntryType::LONGTASK: return longTaskBuffer_; + case PerformanceEntryType::RESOURCE: + return resourceBuffer_; case PerformanceEntryType::_NEXT: throw std::logic_error("Cannot get buffer for _NEXT entry type"); } @@ -143,6 +146,8 @@ class PerformanceEntryReporter { return measureBuffer_; case PerformanceEntryType::LONGTASK: return longTaskBuffer_; + case PerformanceEntryType::RESOURCE: + return resourceBuffer_; case PerformanceEntryType::_NEXT: throw std::logic_error("Cannot get buffer for _NEXT entry type"); } diff --git a/packages/react-native/ReactCommon/react/performance/timeline/tests/PerformanceEntryReporterTest.cpp b/packages/react-native/ReactCommon/react/performance/timeline/tests/PerformanceEntryReporterTest.cpp index bd77d6189e5..2bce5af730c 100644 --- a/packages/react-native/ReactCommon/react/performance/timeline/tests/PerformanceEntryReporterTest.cpp +++ b/packages/react-native/ReactCommon/react/performance/timeline/tests/PerformanceEntryReporterTest.cpp @@ -51,6 +51,7 @@ namespace facebook::react { "PerformanceEntryType::MARK", "PerformanceEntryType::MEASURE", "PerformanceEntryType::EVENT", + "PerformanceEntryType::RESOURCE", }; return std::visit( diff --git a/packages/react-native/src/private/webapis/performance/PerformanceEntry.js b/packages/react-native/src/private/webapis/performance/PerformanceEntry.js index 5e5cd830d01..fcf39c33a67 100644 --- a/packages/react-native/src/private/webapis/performance/PerformanceEntry.js +++ b/packages/react-native/src/private/webapis/performance/PerformanceEntry.js @@ -11,7 +11,12 @@ // flowlint unsafe-getters-setters:off export type DOMHighResTimeStamp = number; -export type PerformanceEntryType = 'mark' | 'measure' | 'event' | 'longtask'; +export type PerformanceEntryType = + | 'mark' + | 'measure' + | 'event' + | 'longtask' + | 'resource'; export type PerformanceEntryJSON = { name: string, diff --git a/packages/react-native/src/private/webapis/performance/internals/RawPerformanceEntry.js b/packages/react-native/src/private/webapis/performance/internals/RawPerformanceEntry.js index 3fc0a41a574..99a0cbb4bfb 100644 --- a/packages/react-native/src/private/webapis/performance/internals/RawPerformanceEntry.js +++ b/packages/react-native/src/private/webapis/performance/internals/RawPerformanceEntry.js @@ -24,6 +24,7 @@ export const RawPerformanceEntryTypeValues = { MEASURE: 2, EVENT: 3, LONGTASK: 4, + RESOURCE: 5, }; export function rawToPerformanceEntry( @@ -95,6 +96,8 @@ export function performanceEntryTypeToRaw( return RawPerformanceEntryTypeValues.EVENT; case 'longtask': return RawPerformanceEntryTypeValues.LONGTASK; + case 'resource': + return RawPerformanceEntryTypeValues.RESOURCE; default: // Verify exhaustive check with Flow (type: empty); diff --git a/packages/react-native/src/private/webapis/performance/specs/NativePerformance.js b/packages/react-native/src/private/webapis/performance/specs/NativePerformance.js index a504e89e930..809037e8a73 100644 --- a/packages/react-native/src/private/webapis/performance/specs/NativePerformance.js +++ b/packages/react-native/src/private/webapis/performance/specs/NativePerformance.js @@ -28,6 +28,15 @@ export type RawPerformanceEntry = { processingStart?: number, processingEnd?: number, interactionId?: number, + + // For PerformanceResourceTiming only + fetchStart?: number, + requestStart?: number, + connectStart?: number, + connectEnd?: number, + responseStart?: number, + responseEnd?: number, + responseStatus?: number, }; export type OpaqueNativeObserverHandle = mixed;