From fbd76541d5688cb683c4c0ae5f6594328f11aca0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rub=C3=A9n=20Norte?= Date: Wed, 1 Apr 2026 08:40:53 -0700 Subject: [PATCH 1/2] Add support for custom timestamps in Event via EVENT_INIT_TIMESTAMP_KEY (#56304) Summary: Add support for specifying a custom `timeStamp` in the `Event` constructor options via a private symbol key (`EVENT_INIT_TIMESTAMP_KEY`) defined in `EventInternals`. This is for internal construction of events using a custom timestamp (instead of event object creation), for use cases like dispatching events from the host platform using the original timestamps. - Added `EVENT_INIT_TIMESTAMP_KEY` symbol to `EventInternals` - Added `setEventInitTimeStamp(eventInit, timeStamp)` helper function in `EventInternals` that validates the type and sets the symbol-keyed property on the event init object - Updated the `Event` constructor to read the custom timestamp from options if present, falling back to `performance.now()` - Added Fantom tests for custom timestamp and zero as a valid timestamp Changelog: [Internal] Reviewed By: huntie Differential Revision: D99076591 --- .../src/private/webapis/dom/events/Event.js | 11 +++++++++- .../dom/events/__tests__/Event-itest.js | 22 ++++++++++++++++++- .../dom/events/internals/EventInternals.js | 19 +++++++++++++++- 3 files changed, 49 insertions(+), 3 deletions(-) diff --git a/packages/react-native/src/private/webapis/dom/events/Event.js b/packages/react-native/src/private/webapis/dom/events/Event.js index f97ead512ab9..f918f9796e56 100644 --- a/packages/react-native/src/private/webapis/dom/events/Event.js +++ b/packages/react-native/src/private/webapis/dom/events/Event.js @@ -21,6 +21,7 @@ import {setPlatformObject} from '../../webidl/PlatformObjects'; import { COMPOSED_PATH_KEY, CURRENT_TARGET_KEY, + EVENT_INIT_TIMESTAMP_KEY, EVENT_PHASE_KEY, IN_PASSIVE_LISTENER_FLAG_KEY, IS_TRUSTED_KEY, @@ -60,7 +61,7 @@ export default class Event { _type: string; _defaultPrevented: boolean = false; - _timeStamp: number = performance.now(); + _timeStamp: number; // $FlowExpectedError[unsupported-syntax] [COMPOSED_PATH_KEY]: boolean = []; @@ -109,6 +110,14 @@ export default class Event { this._bubbles = Boolean(options?.bubbles); this._cancelable = Boolean(options?.cancelable); this._composed = Boolean(options?.composed); + + // For internal construction of events using a custom timestamp (instead of + // event object creation), for use cases like dispatching events from the + // host platform using the original timestamps. + // $FlowExpectedError[prop-missing] + const initTimestamp: number | void = options?.[EVENT_INIT_TIMESTAMP_KEY]; + this._timeStamp = + initTimestamp !== undefined ? initTimestamp : performance.now(); } get bubbles(): boolean { diff --git a/packages/react-native/src/private/webapis/dom/events/__tests__/Event-itest.js b/packages/react-native/src/private/webapis/dom/events/__tests__/Event-itest.js index 21609b28a039..4baa3d2eec41 100644 --- a/packages/react-native/src/private/webapis/dom/events/__tests__/Event-itest.js +++ b/packages/react-native/src/private/webapis/dom/events/__tests__/Event-itest.js @@ -11,7 +11,10 @@ import '@react-native/fantom/src/setUpDefaultReactNativeEnvironment'; import Event from 'react-native/src/private/webapis/dom/events/Event'; -import {setInPassiveListenerFlag} from 'react-native/src/private/webapis/dom/events/internals/EventInternals'; +import { + setEventInitTimeStamp, + setInPassiveListenerFlag, +} from 'react-native/src/private/webapis/dom/events/internals/EventInternals'; describe('Event', () => { it('provides read-only constants for event phases', () => { @@ -233,6 +236,23 @@ describe('Event', () => { expect(event.timeStamp).toBeLessThanOrEqual(upperBoundTimestamp); }); + it('should use a custom timestamp when set via setEventInitTimeStamp', () => { + const customTimestamp = 12345.678; + const options = {}; + setEventInitTimeStamp(options, customTimestamp); + const event = new Event('custom', options); + + expect(event.timeStamp).toBe(customTimestamp); + }); + + it('should accept zero as a valid custom timestamp', () => { + const options = {}; + setEventInitTimeStamp(options, 0); + const event = new Event('custom', options); + + expect(event.timeStamp).toBe(0); + }); + describe('preventDefault', () => { let originalConsoleError; let consoleErrorMock; diff --git a/packages/react-native/src/private/webapis/dom/events/internals/EventInternals.js b/packages/react-native/src/private/webapis/dom/events/internals/EventInternals.js index f16806795857..32f36e2013ee 100644 --- a/packages/react-native/src/private/webapis/dom/events/internals/EventInternals.js +++ b/packages/react-native/src/private/webapis/dom/events/internals/EventInternals.js @@ -14,7 +14,7 @@ * (only with public exports). */ -import type Event, {EventPhase} from '../Event'; +import type Event, {EventInit, EventPhase} from '../Event'; import type EventTarget from '../EventTarget'; export const COMPOSED_PATH_KEY: symbol = Symbol('composedPath'); @@ -30,6 +30,11 @@ export const STOP_IMMEDIATE_PROPAGATION_FLAG_KEY: symbol = Symbol( export const STOP_PROPAGATION_FLAG_KEY: symbol = Symbol('stopPropagationFlag'); export const TARGET_KEY: symbol = Symbol('target'); +// For internal construction of events using a custom timestamp (instead of +// event object creation), for use cases like dispatching events from the host +// platform using the original timestamps. +export const EVENT_INIT_TIMESTAMP_KEY: symbol = Symbol('eventInitTimestamp'); + export function getCurrentTarget(event: Event): EventTarget | null { // $FlowExpectedError[prop-missing] return event[CURRENT_TARGET_KEY]; @@ -118,3 +123,15 @@ export function setTarget(event: Event, target: EventTarget | null): void { // $FlowExpectedError[prop-missing] event[TARGET_KEY] = target; } + +export function setEventInitTimeStamp( + eventInit: EventInit, + timeStamp: number, +): void { + if (typeof timeStamp !== 'number') { + return; + } + // $FlowExpectedError[prop-missing] + // $FlowExpectedError[invalid-computed-prop] + eventInit[EVENT_INIT_TIMESTAMP_KEY] = timeStamp; +} From faf397507eefc2982381dbf1822a9ba48775ae2c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rub=C3=A9n=20Norte?= Date: Wed, 1 Apr 2026 08:40:53 -0700 Subject: [PATCH 2/2] Add HardwareBackPressEvent with native timestamp (#56295) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Summary: Changelog: [Android][Added] - Pass event object to `BackHandler` `hardwareBackPress` events to access timeStamp from native event. BackHandler on Android emits the `hardwareBackPress` event with a `null` payload — no timestamp or event data. This means there is no way for handlers to know when the user actually pressed the back button, which prevents accurate performance tracing for back navigations. This diff: - Sends `SystemClock.uptimeMillis()` as `timestamp` in the native `DeviceEventManagerModule.emitHardwareBackPressed()` event payload - Creates a new `HardwareBackPressEvent` class extending the DOM `Event` class, which overrides the `timeStamp` getter to return the native timestamp (falling back to `performance.now()` if unavailable) - Makes the public constructor throw `TypeError("Illegal constructor")` following the `PerformanceEntry` pattern - Updates all BackHandler platform files (Android, iOS, macOS, Windows) and type definitions (Flow, TypeScript) to create and pass the event to handlers - Updates the BackHandler mock to pass events in `mockPressBack` - Adds Fantom integration tests for both `HardwareBackPressEvent` and `BackHandler` Reviewed By: huntie Differential Revision: D98941079 --- .../Utilities/BackHandler.android.js | 14 +- .../Libraries/Utilities/BackHandler.d.ts | 12 +- .../Libraries/Utilities/BackHandler.ios.js | 4 +- .../Libraries/Utilities/BackHandler.js.flow | 7 +- .../Utilities/HardwareBackPressEvent.js | 22 +++ .../Utilities/__mocks__/BackHandler.js | 12 +- .../Utilities/__tests__/BackHandler-itest.js | 144 ++++++++++++++++++ .../__tests__/HardwareBackPressEvent-itest.js | 65 ++++++++ .../modules/core/DeviceEventManagerModule.kt | 3 +- packages/react-native/ReactNativeApi.d.ts | 10 +- 10 files changed, 280 insertions(+), 13 deletions(-) create mode 100644 packages/react-native/Libraries/Utilities/HardwareBackPressEvent.js create mode 100644 packages/react-native/Libraries/Utilities/__tests__/BackHandler-itest.js create mode 100644 packages/react-native/Libraries/Utilities/__tests__/HardwareBackPressEvent-itest.js diff --git a/packages/react-native/Libraries/Utilities/BackHandler.android.js b/packages/react-native/Libraries/Utilities/BackHandler.android.js index ff468f6500fc..d29e71fa07b7 100644 --- a/packages/react-native/Libraries/Utilities/BackHandler.android.js +++ b/packages/react-native/Libraries/Utilities/BackHandler.android.js @@ -9,18 +9,26 @@ */ import NativeDeviceEventManager from '../../Libraries/NativeModules/specs/NativeDeviceEventManager'; +import {setEventInitTimeStamp} from '../../src/private/webapis/dom/events/internals/EventInternals'; import RCTDeviceEventEmitter from '../EventEmitter/RCTDeviceEventEmitter'; +import {HardwareBackPressEvent} from './HardwareBackPressEvent'; const DEVICE_BACK_EVENT = 'hardwareBackPress'; type BackPressEventName = 'backPress' | 'hardwareBackPress'; -type BackPressHandler = () => ?boolean; +type BackPressHandler = (event: HardwareBackPressEvent) => ?boolean; const _backPressSubscriptions: Array = []; -RCTDeviceEventEmitter.addListener(DEVICE_BACK_EVENT, function () { +RCTDeviceEventEmitter.addListener(DEVICE_BACK_EVENT, function (nativeEvent) { + const options = {}; + const nativeTimestamp = nativeEvent?.timeStamp; + if (nativeTimestamp != null) { + setEventInitTimeStamp(options, nativeTimestamp); + } + const event = new HardwareBackPressEvent(options); for (let i = _backPressSubscriptions.length - 1; i >= 0; i--) { - if (_backPressSubscriptions[i]?.()) { + if (_backPressSubscriptions[i]?.(event)) { return; } } diff --git a/packages/react-native/Libraries/Utilities/BackHandler.d.ts b/packages/react-native/Libraries/Utilities/BackHandler.d.ts index 8ca8e1743d19..ac2a530a9c05 100644 --- a/packages/react-native/Libraries/Utilities/BackHandler.d.ts +++ b/packages/react-native/Libraries/Utilities/BackHandler.d.ts @@ -11,6 +11,16 @@ import {NativeEventSubscription} from '../EventEmitter/RCTNativeAppEventEmitter' export type BackPressEventName = 'hardwareBackPress'; +/** + * Event dispatched when the hardware back button is pressed. + * The `timeStamp` property reflects the native timestamp captured + * when the back press was emitted. + */ +export interface HardwareBackPressEvent { + readonly type: string; + readonly timeStamp: number; +} + /** * Detect hardware back button presses, and programmatically invoke the * default back button functionality to exit the app if there are no @@ -26,7 +36,7 @@ export interface BackHandlerStatic { exitApp(): void; addEventListener( eventName: BackPressEventName, - handler: () => boolean | null | undefined, + handler: (event: HardwareBackPressEvent) => boolean | null | undefined, ): NativeEventSubscription; } diff --git a/packages/react-native/Libraries/Utilities/BackHandler.ios.js b/packages/react-native/Libraries/Utilities/BackHandler.ios.js index 28d811f2f4b0..e9bb65f193bb 100644 --- a/packages/react-native/Libraries/Utilities/BackHandler.ios.js +++ b/packages/react-native/Libraries/Utilities/BackHandler.ios.js @@ -8,8 +8,10 @@ * @format */ +import type {HardwareBackPressEvent} from './HardwareBackPressEvent'; + type BackPressEventName = 'backPress' | 'hardwareBackPress'; -type BackPressHandler = () => ?boolean; +type BackPressHandler = (event: HardwareBackPressEvent) => ?boolean; function emptyFunction(): void {} diff --git a/packages/react-native/Libraries/Utilities/BackHandler.js.flow b/packages/react-native/Libraries/Utilities/BackHandler.js.flow index bf248e260729..eeef9af7b3fa 100644 --- a/packages/react-native/Libraries/Utilities/BackHandler.js.flow +++ b/packages/react-native/Libraries/Utilities/BackHandler.js.flow @@ -12,11 +12,16 @@ export type BackPressEventName = 'backPress' | 'hardwareBackPress'; +export interface HardwareBackPressEvent { + +type: string; + +timeStamp: number; +} + type TBackHandler = { exitApp(): void, addEventListener( eventName: BackPressEventName, - handler: () => ?boolean, + handler: (event: HardwareBackPressEvent) => ?boolean, ): {remove: () => void, ...}, }; diff --git a/packages/react-native/Libraries/Utilities/HardwareBackPressEvent.js b/packages/react-native/Libraries/Utilities/HardwareBackPressEvent.js new file mode 100644 index 000000000000..8576c6060b90 --- /dev/null +++ b/packages/react-native/Libraries/Utilities/HardwareBackPressEvent.js @@ -0,0 +1,22 @@ +/** + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + * @flow strict-local + * @format + */ + +import type {EventInit} from '../../src/private/webapis/dom/events/Event'; + +import Event from '../../src/private/webapis/dom/events/Event'; + +/** + * Event dispatched when the hardware back button is pressed on Android. + */ +export class HardwareBackPressEvent extends Event { + constructor(options?: ?EventInit) { + super('hardwareBackPress', options); + } +} diff --git a/packages/react-native/Libraries/Utilities/__mocks__/BackHandler.js b/packages/react-native/Libraries/Utilities/__mocks__/BackHandler.js index 6563b7869217..9e964a069ba3 100644 --- a/packages/react-native/Libraries/Utilities/__mocks__/BackHandler.js +++ b/packages/react-native/Libraries/Utilities/__mocks__/BackHandler.js @@ -9,15 +9,20 @@ */ import type {BackPressEventName} from '../BackHandler'; +import type {HardwareBackPressEvent} from '../HardwareBackPressEvent'; -const _backPressSubscriptions = new Set<() => ?boolean>(); +import {HardwareBackPressEvent as HardwareBackPressEventClass} from '../HardwareBackPressEvent'; + +const _backPressSubscriptions = new Set< + (event: HardwareBackPressEvent) => ?boolean, +>(); const BackHandler = { exitApp: jest.fn() as () => void, addEventListener: function ( eventName: BackPressEventName, - handler: () => ?boolean, + handler: (event: HardwareBackPressEvent) => ?boolean, ): {remove: () => void, ...} { _backPressSubscriptions.add(handler); return { @@ -28,10 +33,11 @@ const BackHandler = { }, mockPressBack: function () { + const event = new HardwareBackPressEventClass(); let invokeDefault = true; const subscriptions = [..._backPressSubscriptions].reverse(); for (let i = 0; i < subscriptions.length; ++i) { - if (subscriptions[i]()) { + if (subscriptions[i](event)) { invokeDefault = false; break; } diff --git a/packages/react-native/Libraries/Utilities/__tests__/BackHandler-itest.js b/packages/react-native/Libraries/Utilities/__tests__/BackHandler-itest.js new file mode 100644 index 000000000000..a6c3b747bb7e --- /dev/null +++ b/packages/react-native/Libraries/Utilities/__tests__/BackHandler-itest.js @@ -0,0 +1,144 @@ +/** + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + * @flow strict-local + * @format + */ + +import '@react-native/fantom/src/setUpDefaultReactNativeEnvironment'; + +import type {HardwareBackPressEvent} from 'react-native/Libraries/Utilities/BackHandler'; + +import RCTDeviceEventEmitter from 'react-native/Libraries/EventEmitter/RCTDeviceEventEmitter'; +import BackHandler from 'react-native/Libraries/Utilities/BackHandler'; +import {HardwareBackPressEvent as HardwareBackPressEventClass} from 'react-native/Libraries/Utilities/HardwareBackPressEvent'; + +describe('BackHandler', () => { + const subscriptions: Array<{remove: () => void, ...}> = []; + + afterEach(() => { + for (const sub of subscriptions) { + sub.remove(); + } + subscriptions.length = 0; + }); + + it('calls handlers in reverse order (LIFO)', () => { + const callOrder: Array = []; + const handler1 = (_event: HardwareBackPressEvent) => { + callOrder.push('first'); + return false; + }; + const handler2 = (_event: HardwareBackPressEvent) => { + callOrder.push('second'); + return true; + }; + + subscriptions.push( + BackHandler.addEventListener('hardwareBackPress', handler1), + ); + subscriptions.push( + BackHandler.addEventListener('hardwareBackPress', handler2), + ); + + RCTDeviceEventEmitter.emit('hardwareBackPress', {timeStamp: 100}); + + expect(callOrder).toEqual(['second']); + }); + + it('calls all handlers when none return true', () => { + const callOrder: Array = []; + const handler1 = (_event: HardwareBackPressEvent) => { + callOrder.push('first'); + return false; + }; + const handler2 = (_event: HardwareBackPressEvent) => { + callOrder.push('second'); + return false; + }; + + subscriptions.push( + BackHandler.addEventListener('hardwareBackPress', handler1), + ); + subscriptions.push( + BackHandler.addEventListener('hardwareBackPress', handler2), + ); + + RCTDeviceEventEmitter.emit('hardwareBackPress', {timeStamp: 100}); + + expect(callOrder).toEqual(['second', 'first']); + }); + + it('passes HardwareBackPressEvent to handlers', () => { + let receivedEvent: ?HardwareBackPressEvent = null; + const handler = (event: HardwareBackPressEvent) => { + receivedEvent = event; + return true; + }; + + subscriptions.push( + BackHandler.addEventListener('hardwareBackPress', handler), + ); + + RCTDeviceEventEmitter.emit('hardwareBackPress', {timeStamp: 42}); + + expect(receivedEvent).toBeInstanceOf(HardwareBackPressEventClass); + }); + + it('event has native timestamp as timeStamp', () => { + let receivedEvent: ?HardwareBackPressEvent = null; + const handler = (event: HardwareBackPressEvent) => { + receivedEvent = event; + return true; + }; + + subscriptions.push( + BackHandler.addEventListener('hardwareBackPress', handler), + ); + + RCTDeviceEventEmitter.emit('hardwareBackPress', {timeStamp: 42}); + + expect(receivedEvent?.timeStamp).toBe(42); + }); + + it('event falls back to performance.now() when no native timestamp', () => { + let receivedEvent: ?HardwareBackPressEvent = null; + const handler = (event: HardwareBackPressEvent) => { + receivedEvent = event; + return true; + }; + + subscriptions.push( + BackHandler.addEventListener('hardwareBackPress', handler), + ); + + const before = performance.now(); + RCTDeviceEventEmitter.emit('hardwareBackPress', null); + const after = performance.now(); + + const timeStamp = receivedEvent?.timeStamp; + expect(timeStamp).not.toBeNull(); + if (timeStamp != null) { + expect(timeStamp).toBeGreaterThanOrEqual(before); + expect(timeStamp).toBeLessThanOrEqual(after); + } + }); + + it('removes handler on subscription.remove()', () => { + let called = false; + const handler = (_event: HardwareBackPressEvent) => { + called = true; + return true; + }; + + const sub = BackHandler.addEventListener('hardwareBackPress', handler); + sub.remove(); + + RCTDeviceEventEmitter.emit('hardwareBackPress', {timeStamp: 100}); + + expect(called).toBe(false); + }); +}); diff --git a/packages/react-native/Libraries/Utilities/__tests__/HardwareBackPressEvent-itest.js b/packages/react-native/Libraries/Utilities/__tests__/HardwareBackPressEvent-itest.js new file mode 100644 index 000000000000..519da4080d49 --- /dev/null +++ b/packages/react-native/Libraries/Utilities/__tests__/HardwareBackPressEvent-itest.js @@ -0,0 +1,65 @@ +/** + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + * @flow strict-local + * @format + */ + +import '@react-native/fantom/src/setUpDefaultReactNativeEnvironment'; + +import {HardwareBackPressEvent} from 'react-native/Libraries/Utilities/HardwareBackPressEvent'; +import Event from 'react-native/src/private/webapis/dom/events/Event'; +import {setEventInitTimeStamp} from 'react-native/src/private/webapis/dom/events/internals/EventInternals'; + +describe('HardwareBackPressEvent', () => { + it('extends Event', () => { + const event = new HardwareBackPressEvent(); + + expect(event).toBeInstanceOf(Event); + expect(event.type).toBe('hardwareBackPress'); + expect(event.bubbles).toBe(false); + expect(event.cancelable).toBe(false); + expect(event.composed).toBe(false); + }); + + it('uses native timestamp as timeStamp when provided via setEventInitTimeStamp', () => { + const options = {}; + setEventInitTimeStamp(options, 12345); + const event = new HardwareBackPressEvent(options); + + expect(event.timeStamp).toBe(12345); + }); + + it('falls back to performance.now() when no timestamp is provided', () => { + const before = performance.now(); + const event = new HardwareBackPressEvent(); + const after = performance.now(); + + expect(event.timeStamp).toBeGreaterThanOrEqual(before); + expect(event.timeStamp).toBeLessThanOrEqual(after); + }); + + it('falls back to performance.now() when options is undefined', () => { + const before = performance.now(); + const event = new HardwareBackPressEvent(undefined); + const after = performance.now(); + + expect(event.timeStamp).toBeGreaterThanOrEqual(before); + expect(event.timeStamp).toBeLessThanOrEqual(after); + }); + + it('does NOT allow changing the timeStamp value after construction', () => { + const options = {}; + setEventInitTimeStamp(options, 12345); + const event = new HardwareBackPressEvent(options); + + expect(() => { + 'use strict'; + // $FlowExpectedError[cannot-write] + event.timeStamp = 999; + }).toThrow(); + }); +}); diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/modules/core/DeviceEventManagerModule.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/modules/core/DeviceEventManagerModule.kt index a139ffe3424a..9ee720cf8bbc 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/modules/core/DeviceEventManagerModule.kt +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/modules/core/DeviceEventManagerModule.kt @@ -36,7 +36,8 @@ public open class DeviceEventManagerModule( public open fun emitHardwareBackPressed() { val reactApplicationContext: ReactApplicationContext? = getReactApplicationContextIfActiveOrWarn() - reactApplicationContext?.emitDeviceEvent("hardwareBackPress", null) + val map = buildReadableMap { put("timeStamp", System.nanoTime() / 1_000_000.0) } + reactApplicationContext?.emitDeviceEvent("hardwareBackPress", map) } /** Sends an event to the JS instance that a new intent was received. */ diff --git a/packages/react-native/ReactNativeApi.d.ts b/packages/react-native/ReactNativeApi.d.ts index 12e2020d70a7..407700bfb780 100644 --- a/packages/react-native/ReactNativeApi.d.ts +++ b/packages/react-native/ReactNativeApi.d.ts @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<<481366a332c1435df38ef98031869bb9>> + * @generated SignedSource<> * * This file was generated by scripts/js-api/build-types/index.js. */ @@ -2479,6 +2479,10 @@ declare function getWithFallback_DEPRECATED( ): React.ComponentType declare type hairlineWidth = typeof hairlineWidth declare type Handle = number +declare interface HardwareBackPressEvent { + readonly timeStamp: number + readonly type: string +} declare type Headers = { [name: string]: string } @@ -5076,7 +5080,7 @@ declare type TaskProvider = () => HeadlessTask declare type TBackHandler = { addEventListener( eventName: BackPressEventName, - handler: () => boolean | undefined, + handler: (event: HardwareBackPressEvent) => boolean | undefined, ): { remove: () => void } @@ -6015,7 +6019,7 @@ export { AppStateStatus, // 447e5ef2 Appearance, // 00cbaa0a AutoCapitalize, // c0e857a0 - BackHandler, // 0b13c289 + BackHandler, // f139fc69 BackPressEventName, // 4620fb76 BlurEvent, // 870b9bb5 BoxShadowValue, // b679703f