From 988678e0308d247c9ab296789a0e2f04615b7774 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rub=C3=A9n=20Norte?= Date: Thu, 17 Jul 2025 06:39:29 -0700 Subject: [PATCH 1/2] Remove optionality for stable methods of the NativePerformance module (#52668) Summary: Changelog: [internal] These methods have been available for months so no need to consider backwards compatibility with older binaries. Reviewed By: huntie Differential Revision: D78412932 --- .../webapis/performance/EventTiming.js | 4 +- .../webapis/performance/Performance.js | 90 ++++++++++--------- .../performance/specs/NativePerformance.js | 26 +++--- 3 files changed, 62 insertions(+), 58 deletions(-) diff --git a/packages/react-native/src/private/webapis/performance/EventTiming.js b/packages/react-native/src/private/webapis/performance/EventTiming.js index 5e2b446dcfdaac..76d62a18b9dfdb 100644 --- a/packages/react-native/src/private/webapis/performance/EventTiming.js +++ b/packages/react-native/src/private/webapis/performance/EventTiming.js @@ -86,14 +86,14 @@ function getCachedEventCounts(): Map { return cachedEventCounts; } - if (!NativePerformance || !NativePerformance?.getEventCounts) { + if (!NativePerformance) { warnNoNativePerformance(); cachedEventCounts = new Map(); return cachedEventCounts; } const eventCounts = new Map( - NativePerformance.getEventCounts?.() ?? [], + NativePerformance.getEventCounts() ?? [], ); cachedEventCounts = eventCounts; diff --git a/packages/react-native/src/private/webapis/performance/Performance.js b/packages/react-native/src/private/webapis/performance/Performance.js index 789e901a14ec6b..d6725d5bfdf58d 100644 --- a/packages/react-native/src/private/webapis/performance/Performance.js +++ b/packages/react-native/src/private/webapis/performance/Performance.js @@ -98,53 +98,56 @@ export default class Performance { // Get the current JS memory information. get memory(): MemoryInfo { - if (NativePerformance?.getSimpleMemoryInfo) { - // JSI API implementations may have different variants of names for the JS - // heap information we need here. We will parse the result based on our - // guess of the implementation for now. - const memoryInfo = NativePerformance.getSimpleMemoryInfo(); - if (memoryInfo.hasOwnProperty('hermes_heapSize')) { - // We got memory information from Hermes - const { - hermes_heapSize: totalJSHeapSize, - hermes_allocatedBytes: usedJSHeapSize, - } = memoryInfo; - - return new MemoryInfo({ - jsHeapSizeLimit: null, // We don't know the heap size limit from Hermes. - totalJSHeapSize, - usedJSHeapSize, - }); - } else { - // JSC and V8 has no native implementations for memory information in JSI::Instrumentation - return new MemoryInfo(); - } + if (!NativePerformance) { + warnNoNativePerformance(); + return new MemoryInfo(); } - return new MemoryInfo(); + // JSI API implementations may have different variants of names for the JS + // heap information we need here. We will parse the result based on our + // guess of the implementation for now. + const memoryInfo = NativePerformance.getSimpleMemoryInfo(); + if (memoryInfo.hasOwnProperty('hermes_heapSize')) { + // We got memory information from Hermes + const { + hermes_heapSize: totalJSHeapSize, + hermes_allocatedBytes: usedJSHeapSize, + } = memoryInfo; + + return new MemoryInfo({ + jsHeapSizeLimit: null, // We don't know the heap size limit from Hermes. + totalJSHeapSize, + usedJSHeapSize, + }); + } else { + // JSC and V8 has no native implementations for memory information in JSI::Instrumentation + return new MemoryInfo(); + } } // Startup metrics is not used in web, but only in React Native. get rnStartupTiming(): ReactNativeStartupTiming { - if (NativePerformance?.getReactNativeStartupTiming) { - const { - startTime, - endTime, - initializeRuntimeStart, - initializeRuntimeEnd, - executeJavaScriptBundleEntryPointStart, - executeJavaScriptBundleEntryPointEnd, - } = NativePerformance.getReactNativeStartupTiming(); - return new ReactNativeStartupTiming({ - startTime, - endTime, - initializeRuntimeStart, - initializeRuntimeEnd, - executeJavaScriptBundleEntryPointStart, - executeJavaScriptBundleEntryPointEnd, - }); + if (!NativePerformance) { + warnNoNativePerformance(); + return new ReactNativeStartupTiming(); } - return new ReactNativeStartupTiming(); + + const { + startTime, + endTime, + initializeRuntimeStart, + initializeRuntimeEnd, + executeJavaScriptBundleEntryPointStart, + executeJavaScriptBundleEntryPointEnd, + } = NativePerformance.getReactNativeStartupTiming(); + return new ReactNativeStartupTiming({ + startTime, + endTime, + initializeRuntimeStart, + initializeRuntimeEnd, + executeJavaScriptBundleEntryPointStart, + executeJavaScriptBundleEntryPointEnd, + }); } mark( @@ -434,10 +437,11 @@ export default class Performance { * https://www.w3.org/TR/performance-timeline/#extensions-to-the-performance-interface */ getEntries(): PerformanceEntryList { - if (!NativePerformance?.getEntries) { + if (!NativePerformance) { warnNoNativePerformance(); return []; } + return NativePerformance.getEntries().map(rawToPerformanceEntry); } @@ -450,7 +454,7 @@ export default class Performance { return []; } - if (!NativePerformance?.getEntriesByType) { + if (!NativePerformance) { warnNoNativePerformance(); return []; } @@ -472,7 +476,7 @@ export default class Performance { return []; } - if (!NativePerformance?.getEntriesByName) { + if (!NativePerformance) { warnNoNativePerformance(); return []; } 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 eeb08d788e0d49..640138cee0abb3 100644 --- a/packages/react-native/src/private/webapis/performance/specs/NativePerformance.js +++ b/packages/react-native/src/private/webapis/performance/specs/NativePerformance.js @@ -53,7 +53,7 @@ export type PerformanceObserverInit = { }; export interface Spec extends TurboModule { - +now?: () => number; + +now: () => number; +reportMark?: (name: string, startTime: number, entry: mixed) => void; +reportMeasure?: ( name: string, @@ -62,36 +62,36 @@ export interface Spec extends TurboModule { entry: mixed, ) => void; +getMarkTime?: (name: string) => ?number; - +clearMarks?: (entryName?: string) => void; - +clearMeasures?: (entryName?: string) => void; - +getEntries?: () => $ReadOnlyArray; - +getEntriesByName?: ( + +clearMarks: (entryName?: string) => void; + +clearMeasures: (entryName?: string) => void; + +getEntries: () => $ReadOnlyArray; + +getEntriesByName: ( entryName: string, entryType?: ?RawPerformanceEntryType, ) => $ReadOnlyArray; - +getEntriesByType?: ( + +getEntriesByType: ( entryType: RawPerformanceEntryType, ) => $ReadOnlyArray; - +getEventCounts?: () => $ReadOnlyArray<[string, number]>; + +getEventCounts: () => $ReadOnlyArray<[string, number]>; +getSimpleMemoryInfo: () => NativeMemoryInfo; +getReactNativeStartupTiming: () => ReactNativeStartupTiming; - +createObserver?: ( + +createObserver: ( callback: NativeBatchedObserverCallback, ) => OpaqueNativeObserverHandle; - +getDroppedEntriesCount?: (observer: OpaqueNativeObserverHandle) => number; + +getDroppedEntriesCount: (observer: OpaqueNativeObserverHandle) => number; - +observe?: ( + +observe: ( observer: OpaqueNativeObserverHandle, options: PerformanceObserverInit, ) => void; - +disconnect?: (observer: OpaqueNativeObserverHandle) => void; - +takeRecords?: ( + +disconnect: (observer: OpaqueNativeObserverHandle) => void; + +takeRecords: ( observer: OpaqueNativeObserverHandle, sort: boolean, ) => $ReadOnlyArray; - +getSupportedPerformanceEntryTypes?: () => $ReadOnlyArray; + +getSupportedPerformanceEntryTypes: () => $ReadOnlyArray; +setCurrentTimeStampForTesting?: (timeStamp: number) => void; +clearEventCountsForTesting?: () => void; From 1a65feadbc05644968e212f937808c62ba07bd7e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rub=C3=A9n=20Norte?= Date: Thu, 17 Jul 2025 06:39:29 -0700 Subject: [PATCH 2/2] Assume NativePerformance will be available if the Performance module is loaded MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Summary: Changelog: [internal] When setting up the global `performance` value, we check if the native module exists to decide what version to setup: the legacy "barebones" version or the modern version that's mostly spec compliant. As we do that check and we shouldn't be requiring the module from anywhere else, it should be safe to always assume the module will be defined if we load the `Performance` class, so we can avoid checks in all methods. NOTE: I've kept some checks for a few methods that are still not fully propagated (new methods like `reportMark`, `reportMeasure` and `getMarkTime`). This improves performance slightly for `performance` methods: * Before | (index) | Task name | Latency average (ns) | Latency median (ns) | Throughput average (ops/s) | Throughput median (ops/s) | Samples | | ------- | --------------------------------------------------------- | -------------------- | ------------------- | -------------------------- | ------------------------- | ------- | | 0 | 'mark (default)' | '1803.32 ± 0.71%' | '1763.00' | '563849 ± 0.01%' | '567215' | 554908 | | 1 | 'mark (with custom startTime)' | '1762.39 ± 1.67%' | '1692.00' | '587832 ± 0.01%' | '591017' | 567414 | | 2 | 'measure (default)' | '1879.47 ± 1.44%' | '1813.00' | '548962 ± 0.01%' | '551572' | 532064 | | 3 | 'measure (with start and end timestamps)' | '1916.65 ± 0.84%' | '1873.00' | '531258 ± 0.01%' | '533903' | 521743 | | 4 | 'measure (with mark names)' | '2049.84 ± 0.44%' | '2013.00' | '492799 ± 0.01%' | '496771' | 487844 | | 5 | 'clearMarks' | '719.87 ± 0.04%' | '711.00' | '1403602 ± 0.01%' | '1406470' | 1389136 | | 6 | 'clearMeasures' | '710.04 ± 0.04%' | '701.00' | '1421610 ± 0.01%' | '1426534' | 1408373 | | 7 | 'mark + clearMarks' | '2256.56 ± 1.10%' | '2143.00' | '460721 ± 0.02%' | '466636' | 443152 | | 8 | 'measure + clearMeasures (with start and end timestamps)' | '2345.44 ± 1.11%' | '2244.00' | '442395 ± 0.02%' | '445633' | 426360 | | 9 | 'measure + clearMeasures (with mark names)' | '2349.55 ± 0.61%' | '2283.00' | '434370 ± 0.02%' | '438020' | 425613 | * After | (index) | Task name | Latency average (ns) | Latency median (ns) | Throughput average (ops/s) | Throughput median (ops/s) | Samples | | ------- | --------------------------------------------------------- | -------------------- | ------------------- | -------------------------- | ------------------------- | ------- | | 0 | 'mark (default)' | '1791.47 ± 1.08%' | '1732.00' | '573787 ± 0.01%' | '577367' | 558202 | | 1 | 'mark (with custom startTime)' | '1699.41 ± 1.27%' | '1642.00' | '605188 ± 0.01%' | '609013' | 588441 | | 2 | 'measure (default)' | '1820.92 ± 1.39%' | '1763.00' | '563437 ± 0.01%' | '567215' | 549173 | | 3 | 'measure (with start and end timestamps)' | '1923.57 ± 1.65%' | '1852.00' | '537112 ± 0.01%' | '539957' | 519867 | | 4 | 'measure (with mark names)' | '2036.09 ± 1.05%' | '1983.00' | '500406 ± 0.01%' | '504286' | 491139 | | 5 | 'clearMarks' | '657.49 ± 0.07%' | '641.00' | '1543793 ± 0.01%' | '1560062' | 1520939 | | 6 | 'clearMeasures' | '669.02 ± 0.09%' | '651.00' | '1520386 ± 0.01%' | '1536098' | 1494730 | | 7 | 'mark + clearMarks' | '2213.09 ± 1.53%' | '2103.00' | '470008 ± 0.02%' | '475511' | 451858 | | 8 | 'measure + clearMeasures (with start and end timestamps)' | '2353.15 ± 1.27%' | '2214.00' | '448563 ± 0.02%' | '451671' | 424962 | | 9 | 'measure + clearMeasures (with mark names)' | '2298.28 ± 0.62%' | '2243.00' | '441703 ± 0.02%' | '445831' | 435108 | Reviewed By: hoxyq Differential Revision: D78412931 --- .../Libraries/Core/setUpPerformance.js | 3 +- .../webapis/performance/EventTiming.js | 12 ++--- .../webapis/performance/Performance.js | 50 ++++--------------- .../performance/PerformanceObserver.js | 37 +++----------- .../__tests__/EventTimingAPI-itest.js | 6 ++- .../performance/__tests__/UserTiming-itest.js | 23 +++++---- 6 files changed, 40 insertions(+), 91 deletions(-) diff --git a/packages/react-native/Libraries/Core/setUpPerformance.js b/packages/react-native/Libraries/Core/setUpPerformance.js index 2087c74cc1e5c1..edb00ce81e211b 100644 --- a/packages/react-native/Libraries/Core/setUpPerformance.js +++ b/packages/react-native/Libraries/Core/setUpPerformance.js @@ -8,12 +8,13 @@ * @format */ -import Performance from '../../src/private/webapis/performance/Performance'; import NativePerformance from '../../src/private/webapis/performance/specs/NativePerformance'; // In case if the native implementation of the Performance API is available, use it, // otherwise fall back to the legacy/default one, which only defines 'Performance.now()' if (NativePerformance) { + const Performance = + require('../../src/private/webapis/performance/Performance').default; // $FlowExpectedError[cannot-write] global.performance = new Performance(); } else { diff --git a/packages/react-native/src/private/webapis/performance/EventTiming.js b/packages/react-native/src/private/webapis/performance/EventTiming.js index 76d62a18b9dfdb..8f96f8d6ba8b65 100644 --- a/packages/react-native/src/private/webapis/performance/EventTiming.js +++ b/packages/react-native/src/private/webapis/performance/EventTiming.js @@ -15,9 +15,11 @@ import type { PerformanceEntryJSON, } from './PerformanceEntry'; -import {warnNoNativePerformance} from './internals/Utilities'; import {PerformanceEntry} from './PerformanceEntry'; -import NativePerformance from './specs/NativePerformance'; +import MaybeNativePerformance from './specs/NativePerformance'; +import nullthrows from 'nullthrows'; + +const NativePerformance = nullthrows(MaybeNativePerformance); export type PerformanceEventTimingJSON = { ...PerformanceEntryJSON, @@ -86,12 +88,6 @@ function getCachedEventCounts(): Map { return cachedEventCounts; } - if (!NativePerformance) { - warnNoNativePerformance(); - cachedEventCounts = new Map(); - return cachedEventCounts; - } - const eventCounts = new Map( NativePerformance.getEventCounts() ?? [], ); diff --git a/packages/react-native/src/private/webapis/performance/Performance.js b/packages/react-native/src/private/webapis/performance/Performance.js index d6725d5bfdf58d..c652481cd376cb 100644 --- a/packages/react-native/src/private/webapis/performance/Performance.js +++ b/packages/react-native/src/private/webapis/performance/Performance.js @@ -35,8 +35,9 @@ import { } from './internals/Utilities'; import MemoryInfo from './MemoryInfo'; import ReactNativeStartupTiming from './ReactNativeStartupTiming'; -import NativePerformance from './specs/NativePerformance'; +import MaybeNativePerformance from './specs/NativePerformance'; import {PerformanceMark, PerformanceMeasure} from './UserTiming'; +import nullthrows from 'nullthrows'; export type PerformanceMeasureOptions = | $ReadOnly<{ @@ -58,11 +59,13 @@ export type PerformanceMeasureOptions = const ENTRY_TYPES_AVAILABLE_FROM_TIMELINE: $ReadOnlyArray = ['mark', 'measure']; -const cachedReportMark = NativePerformance?.reportMark; -const cachedReportMeasure = NativePerformance?.reportMeasure; -const cachedGetMarkTime = NativePerformance?.getMarkTime; -const cachedNativeClearMarks = NativePerformance?.clearMarks; -const cachedNativeClearMeasures = NativePerformance?.clearMeasures; +const NativePerformance = nullthrows(MaybeNativePerformance); + +const cachedReportMark = NativePerformance.reportMark; +const cachedReportMeasure = NativePerformance.reportMeasure; +const cachedGetMarkTime = NativePerformance.getMarkTime; +const cachedNativeClearMarks = NativePerformance.clearMarks; +const cachedNativeClearMeasures = NativePerformance.clearMeasures; const MARK_OPTIONS_REUSABLE_OBJECT: {...PerformanceMarkOptions} = { startTime: 0, @@ -98,11 +101,6 @@ export default class Performance { // Get the current JS memory information. get memory(): MemoryInfo { - if (!NativePerformance) { - warnNoNativePerformance(); - return new MemoryInfo(); - } - // JSI API implementations may have different variants of names for the JS // heap information we need here. We will parse the result based on our // guess of the implementation for now. @@ -127,11 +125,6 @@ export default class Performance { // Startup metrics is not used in web, but only in React Native. get rnStartupTiming(): ReactNativeStartupTiming { - if (!NativePerformance) { - warnNoNativePerformance(); - return new ReactNativeStartupTiming(); - } - const { startTime, endTime, @@ -220,11 +213,6 @@ export default class Performance { } clearMarks(markName?: string): void { - if (!cachedNativeClearMarks) { - warnNoNativePerformance(); - return; - } - cachedNativeClearMarks(markName); } @@ -417,11 +405,6 @@ export default class Performance { } clearMeasures(measureName?: string): void { - if (!cachedNativeClearMeasures) { - warnNoNativePerformance(); - return; - } - cachedNativeClearMeasures(measureName); } @@ -437,11 +420,6 @@ export default class Performance { * https://www.w3.org/TR/performance-timeline/#extensions-to-the-performance-interface */ getEntries(): PerformanceEntryList { - if (!NativePerformance) { - warnNoNativePerformance(); - return []; - } - return NativePerformance.getEntries().map(rawToPerformanceEntry); } @@ -454,11 +432,6 @@ export default class Performance { return []; } - if (!NativePerformance) { - warnNoNativePerformance(); - return []; - } - return NativePerformance.getEntriesByType( performanceEntryTypeToRaw(entryType), ).map(rawToPerformanceEntry); @@ -476,11 +449,6 @@ export default class Performance { return []; } - if (!NativePerformance) { - warnNoNativePerformance(); - return []; - } - return NativePerformance.getEntriesByName( entryName, entryType != null ? performanceEntryTypeToRaw(entryType) : undefined, diff --git a/packages/react-native/src/private/webapis/performance/PerformanceObserver.js b/packages/react-native/src/private/webapis/performance/PerformanceObserver.js index 6870d4a9f2a4f5..c576a4451f6658 100644 --- a/packages/react-native/src/private/webapis/performance/PerformanceObserver.js +++ b/packages/react-native/src/private/webapis/performance/PerformanceObserver.js @@ -21,12 +21,13 @@ import { rawToPerformanceEntry, rawToPerformanceEntryType, } from './internals/RawPerformanceEntry'; -import {warnNoNativePerformance} from './internals/Utilities'; -import NativePerformance from './specs/NativePerformance'; +import MaybeNativePerformance from './specs/NativePerformance'; import nullthrows from 'nullthrows'; export {PerformanceEntry} from './PerformanceEntry'; +const NativePerformance = nullthrows(MaybeNativePerformance); + export class PerformanceObserverEntryList { #entries: PerformanceEntryList; @@ -75,13 +76,6 @@ export interface PerformanceObserverInit { } function getSupportedPerformanceEntryTypes(): $ReadOnlyArray { - if (!NativePerformance) { - return Object.freeze([]); - } - if (!NativePerformance.getSupportedPerformanceEntryTypes) { - // fallback if getSupportedPerformanceEntryTypes is not defined on native side - return Object.freeze(['mark', 'measure', 'event']); - } return Object.freeze( NativePerformance.getSupportedPerformanceEntryTypes().map( rawToPerformanceEntryType, @@ -120,11 +114,6 @@ export class PerformanceObserver { } observe(options: PerformanceObserverInit): void { - if (!NativePerformance || NativePerformance.observe == null) { - warnNoNativePerformance(); - return; - } - this.#validateObserveOptions(options); if (this.#nativeObserverHandle == null) { @@ -135,12 +124,12 @@ export class PerformanceObserver { if (options.entryTypes) { this.#type = 'multiple'; - NativePerformance.observe?.(observerHandle, { + NativePerformance.observe(observerHandle, { entryTypes: options.entryTypes.map(performanceEntryTypeToRaw), }); } else if (options.type) { this.#type = 'single'; - NativePerformance.observe?.(observerHandle, { + NativePerformance.observe(observerHandle, { type: performanceEntryTypeToRaw(options.type), buffered: options.buffered, durationThreshold: options.durationThreshold, @@ -149,12 +138,7 @@ export class PerformanceObserver { } disconnect(): void { - if (!NativePerformance) { - warnNoNativePerformance(); - return; - } - - if (this.#nativeObserverHandle == null || !NativePerformance.disconnect) { + if (this.#nativeObserverHandle == null) { return; } @@ -162,16 +146,11 @@ export class PerformanceObserver { } #createNativeObserver(): OpaqueNativeObserverHandle | null { - if (!NativePerformance || !NativePerformance.createObserver) { - warnNoNativePerformance(); - return null; - } - this.#calledAtLeastOnce = false; const observerHandle: OpaqueNativeObserverHandle = NativePerformance.createObserver(() => { - const rawEntries = NativePerformance.takeRecords?.( + const rawEntries = NativePerformance.takeRecords( observerHandle, true, // sort records ); @@ -185,7 +164,7 @@ export class PerformanceObserver { let droppedEntriesCount = 0; if (!this.#calledAtLeastOnce) { droppedEntriesCount = - NativePerformance.getDroppedEntriesCount?.(observerHandle) ?? 0; + NativePerformance.getDroppedEntriesCount(observerHandle); this.#calledAtLeastOnce = true; } diff --git a/packages/react-native/src/private/webapis/performance/__tests__/EventTimingAPI-itest.js b/packages/react-native/src/private/webapis/performance/__tests__/EventTimingAPI-itest.js index 9f9e6615ccf6ff..5c46106f95d7fb 100644 --- a/packages/react-native/src/private/webapis/performance/__tests__/EventTimingAPI-itest.js +++ b/packages/react-native/src/private/webapis/performance/__tests__/EventTimingAPI-itest.js @@ -13,7 +13,7 @@ import '@react-native/fantom/src/setUpDefaultReactNativeEnvironment'; import type Performance from 'react-native/src/private/webapis/performance/Performance'; import type {PerformanceObserverEntryList} from 'react-native/src/private/webapis/performance/PerformanceObserver'; -import NativePerformance from '../specs/NativePerformance'; +import MaybeNativePerformance from '../specs/NativePerformance'; import * as Fantom from '@react-native/fantom'; import nullthrows from 'nullthrows'; import {useState} from 'react'; @@ -22,6 +22,8 @@ import setUpPerformanceObserver from 'react-native/src/private/setup/setUpPerfor import {PerformanceEventTiming} from 'react-native/src/private/webapis/performance/EventTiming'; import {PerformanceObserver} from 'react-native/src/private/webapis/performance/PerformanceObserver'; +const NativePerformance = nullthrows(MaybeNativePerformance); + setUpPerformanceObserver(); declare var performance: Performance; @@ -193,7 +195,7 @@ describe('Event Timing API', () => { }); it('reports number of dispatched events via performance.eventCounts', () => { - NativePerformance?.clearEventCountsForTesting?.(); + NativePerformance.clearEventCountsForTesting?.(); const root = Fantom.createRoot(); Fantom.runTask(() => { diff --git a/packages/react-native/src/private/webapis/performance/__tests__/UserTiming-itest.js b/packages/react-native/src/private/webapis/performance/__tests__/UserTiming-itest.js index 85fa6443510613..e1a469740062f8 100644 --- a/packages/react-native/src/private/webapis/performance/__tests__/UserTiming-itest.js +++ b/packages/react-native/src/private/webapis/performance/__tests__/UserTiming-itest.js @@ -18,8 +18,11 @@ import type { import ensureInstance from '../../../__tests__/utilities/ensureInstance'; import DOMException from '../../errors/DOMException'; -import NativePerformance from '../specs/NativePerformance'; +import MaybeNativePerformance from '../specs/NativePerformance'; import {PerformanceMark, PerformanceMeasure} from '../UserTiming'; +import nullthrows from 'nullthrows'; + +const NativePerformance = nullthrows(MaybeNativePerformance); declare var performance: Performance; @@ -44,7 +47,7 @@ describe('User Timing', () => { describe('mark', () => { it('works with default timestamp', () => { - NativePerformance?.setCurrentTimeStampForTesting?.(25); + NativePerformance.setCurrentTimeStampForTesting?.(25); const mark = performance.mark('mark-now'); @@ -144,7 +147,7 @@ describe('User Timing', () => { describe('measure', () => { describe('with measureOptions', () => { it('uses 0 as default start and now as default end', () => { - NativePerformance?.setCurrentTimeStampForTesting?.(25); + NativePerformance.setCurrentTimeStampForTesting?.(25); const measure = performance.measure('measure-with-defaults', {}); @@ -157,7 +160,7 @@ describe('User Timing', () => { }); it('works with a start timestamp', () => { - NativePerformance?.setCurrentTimeStampForTesting?.(25); + NativePerformance.setCurrentTimeStampForTesting?.(25); const measure = performance.measure('measure-with-start-timestamp', { start: 10, @@ -172,7 +175,7 @@ describe('User Timing', () => { }); it('works with start mark', () => { - NativePerformance?.setCurrentTimeStampForTesting?.(25); + NativePerformance.setCurrentTimeStampForTesting?.(25); performance.mark('start-mark', { startTime: 10, @@ -191,7 +194,7 @@ describe('User Timing', () => { }); it('works with end mark', () => { - NativePerformance?.setCurrentTimeStampForTesting?.(25); + NativePerformance.setCurrentTimeStampForTesting?.(25); performance.mark('end-mark', { startTime: 50, @@ -210,7 +213,7 @@ describe('User Timing', () => { }); it('works with start mark and end mark', () => { - NativePerformance?.setCurrentTimeStampForTesting?.(25); + NativePerformance.setCurrentTimeStampForTesting?.(25); performance.mark('start-mark', { startTime: 10, @@ -375,7 +378,7 @@ describe('User Timing', () => { describe('with startMark / endMark', () => { it('uses 0 as default start and now as default end', () => { - NativePerformance?.setCurrentTimeStampForTesting?.(25); + NativePerformance.setCurrentTimeStampForTesting?.(25); const measure = performance.measure('measure-with-defaults'); @@ -388,7 +391,7 @@ describe('User Timing', () => { }); it('works with startMark', () => { - NativePerformance?.setCurrentTimeStampForTesting?.(25); + NativePerformance.setCurrentTimeStampForTesting?.(25); performance.mark('start-mark', { startTime: 10, @@ -408,7 +411,7 @@ describe('User Timing', () => { }); it('works with startMark and endMark', () => { - NativePerformance?.setCurrentTimeStampForTesting?.(25); + NativePerformance.setCurrentTimeStampForTesting?.(25); performance.mark('start-mark', { startTime: 10,