Skip to content

Commit 830b34d

Browse files
rubennortemeta-codesync[bot]
authored andcommitted
Use global DOM types in Fantom tests (#58569)
Summary: Pull Request resolved: #58569 Replace Fantom test imports of internal Event, EventTarget, AbortController, and feature flag modules with supported exports and global DOM APIs. Add the missing static Event phase constants to the DOM Flow declarations so constructor constants remain typed, and route trusted-event coverage through `dispatchNativeEvent`. Changelog: [Internal] Reviewed By: mdvacca Differential Revision: D120528709
1 parent 194c48d commit 830b34d

19 files changed

Lines changed: 68 additions & 52 deletions

‎packages/react-native/flow/dom.js.flow‎

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -618,7 +618,7 @@ type Event$Init = {
618618

619619
// https://dom.spec.whatwg.org/#interface-event
620620
declare class Event {
621-
constructor(type: string, eventInitDict?: Event$Init): void;
621+
constructor(type: string, eventInitDict?: ?Event$Init): void;
622622
/**
623623
* Returns the type of event, e.g. "click", "hashchange", or "submit".
624624
*/
@@ -711,10 +711,17 @@ declare class Event {
711711
/** Non-standard. See Event.prototype.composed */
712712
readonly scoped: boolean;
713713

714+
cancelBubble: boolean;
715+
714716
/**
715717
* @deprecated
716718
*/
717719
initEvent(type: string, bubbles: boolean, cancelable: boolean): void;
720+
721+
static readonly NONE: 0;
722+
static readonly CAPTURING_PHASE: 1;
723+
static readonly AT_TARGET: 2;
724+
static readonly BUBBLING_PHASE: 3;
718725
}
719726

720727
type CustomEvent$Init = {...Event$Init, detail?: any, ...};

‎packages/react-native/src/private/__tests__/utilities/__tests__/ShadowNodeRevisionGetter-itest.js‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ import {createShadowNodeReferenceGetterRef} from '../ShadowNodeRevisionGetter';
1515
import * as Fantom from '@react-native/fantom';
1616
import * as React from 'react';
1717
import {ScrollView, View} from 'react-native';
18-
import * as ReactNativeFeatureFlags from 'react-native/src/private/featureflags/ReactNativeFeatureFlags';
18+
import {ReactNativeFeatureFlags} from 'react-native/react-private-interface';
1919

2020
test('base case when cloning results in revision +1', () => {
2121
const root = Fantom.createRoot();

‎packages/react-native/src/private/renderer/core/__tests__/EventTargetDispatching-itest.js‎

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,7 @@ import type {NativePointerEvent, PointerEvent} from 'react-native';
1717
import * as Fantom from '@react-native/fantom';
1818
import * as React from 'react';
1919
import {View} from 'react-native';
20-
import * as ReactNativeFeatureFlags from 'react-native/src/private/featureflags/ReactNativeFeatureFlags';
21-
import Event from 'react-native/src/private/webapis/dom/events/Event';
20+
import {ReactNativeFeatureFlags} from 'react-native/react-private-interface';
2221

2322
// Temporary cast until ReadOnlyNode extends EventTarget ungated.
2423
function asEventTarget(node: ?interface {}): EventTarget {
@@ -1640,12 +1639,14 @@ describe('EventTarget-based Event Dispatching', () => {
16401639
describe('direct events (rnIsDirect) — Event construction validation', () => {
16411640
it('allows constructing a direct event that does not bubble', () => {
16421641
const event = new Event('layout', {rnIsDirect: true});
1642+
// $FlowFixMe[prop-missing] React Native-specific Event field.
16431643
expect(event.rnIsDirect).toBe(true);
16441644
expect(event.bubbles).toBe(false);
16451645
});
16461646

16471647
it('defaults rnIsDirect to false', () => {
16481648
const event = new Event('layout');
1649+
// $FlowFixMe[prop-missing] React Native-specific Event field.
16491650
expect(event.rnIsDirect).toBe(false);
16501651
});
16511652

@@ -1752,6 +1753,7 @@ describe('EventTarget-based Event Dispatching', () => {
17521753
);
17531754

17541755
expect(handler).toHaveBeenCalled();
1756+
// $FlowFixMe[prop-missing] Flow's global Event type omits static constants.
17551757
expect(observedPhase).toBe(Event.AT_TARGET);
17561758
// Event path is just the target node.
17571759
expect(observedPathLength).toBe(1);

‎packages/react-native/src/private/renderer/events/dispatchNativeEvent.js‎

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
* @format
99
*/
1010

11-
import type EventTarget from '../../webapis/dom/events/EventTarget';
11+
import type InternalEventTarget from '../../webapis/dom/events/EventTarget';
1212

1313
import {
1414
customBubblingEventTypes,
@@ -41,8 +41,11 @@ export default function dispatchNativeEvent(
4141
type: string,
4242
payload: {[string]: unknown},
4343
): void {
44+
// $FlowFixMe[incompatible-type] The global is backed by this implementation.
45+
const internalTarget = target as InternalEventTarget;
46+
4447
// Process responder events before normal event dispatch.
45-
processResponderEvent(type, target, payload);
48+
processResponderEvent(type, internalTarget, payload);
4649

4750
try {
4851
// Normal EventTarget dispatch
@@ -117,7 +120,7 @@ export default function dispatchNativeEvent(
117120
// rethrown synchronously (matching the legacy plugin path) rather than
118121
// deferred to a new task, keeping it catchable by React error boundaries
119122
// and the native event call.
120-
dispatchTrustedEvent(target, syntheticEvent, true);
123+
dispatchTrustedEvent(internalTarget, syntheticEvent, true);
121124
}
122125
} finally {
123126
// Rethrow the first error caught during responder lifecycle dispatch,

‎packages/react-native/src/private/setup/__tests__/setUpDefaultReactNativeEnvironment-Globals-IntersectionObserver-itest.js‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212

1313
import '@react-native/fantom/src/setUpDefaultReactNativeEnvironment';
1414

15-
import * as ReactNativeFeatureFlags from 'react-native/src/private/featureflags/ReactNativeFeatureFlags';
15+
import {ReactNativeFeatureFlags} from 'react-native/react-private-interface';
1616

1717
declare var IntersectionObserverEntry: unknown;
1818

‎packages/react-native/src/private/setup/__tests__/setUpDefaultReactNativeEnvironment-Globals-MutationObserver-itest.js‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212

1313
import '@react-native/fantom/src/setUpDefaultReactNativeEnvironment';
1414

15-
import * as ReactNativeFeatureFlags from 'react-native/src/private/featureflags/ReactNativeFeatureFlags';
15+
import {ReactNativeFeatureFlags} from 'react-native/react-private-interface';
1616

1717
declare var MutationRecord: unknown;
1818

‎packages/react-native/src/private/setup/__tests__/setUpDefaultReactNativeEnvironment-Globals-ResizeObserver-itest.js‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212

1313
import '@react-native/fantom/src/setUpDefaultReactNativeEnvironment';
1414

15-
import * as ReactNativeFeatureFlags from 'react-native/src/private/featureflags/ReactNativeFeatureFlags';
15+
import {ReactNativeFeatureFlags} from 'react-native/react-private-interface';
1616

1717
declare var ResizeObserverEntry: unknown;
1818
declare var ResizeObserverSize: unknown;

‎packages/react-native/src/private/webapis/dom/abort-api/__tests__/AbortController-itest.js‎

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,11 +13,7 @@ import '@react-native/fantom/src/setUpDefaultReactNativeEnvironment';
1313
import type {TimerMock} from '@react-native/fantom';
1414

1515
import DOMException from '../../../errors/DOMException';
16-
import {AbortController} from '../AbortController';
17-
import {AbortSignal_public as AbortSignal} from '../AbortSignal';
1816
import * as Fantom from '@react-native/fantom';
19-
import Event from 'react-native/src/private/webapis/dom/events/Event';
20-
import EventTarget from 'react-native/src/private/webapis/dom/events/EventTarget';
2117

2218
let listenerCallOrder = 0;
2319

‎packages/react-native/src/private/webapis/dom/events/__tests__/Event-itest.js‎

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -10,12 +10,15 @@
1010

1111
import '@react-native/fantom/src/setUpDefaultReactNativeEnvironment';
1212

13-
import Event from 'react-native/src/private/webapis/dom/events/Event';
1413
import {
1514
setEventInitTimeStamp,
1615
setInPassiveListenerFlag,
1716
} from 'react-native/src/private/webapis/dom/events/internals/EventInternals';
1817

18+
type EventOptions = Event$Init & {
19+
rnIsDirect?: boolean,
20+
};
21+
1922
describe('Event', () => {
2023
it('provides read-only constants for event phases', () => {
2124
'use strict';
@@ -121,13 +124,12 @@ describe('Event', () => {
121124
}).not.toThrow();
122125

123126
expect(() => {
124-
// $FlowExpectedError[incompatible-exact]
125-
// $FlowExpectedError[prop-missing]
127+
// $FlowExpectedError[incompatible-type]
126128
return new Event('custom', class {});
127129
}).not.toThrow();
128130

129131
expect(() => {
130-
// $FlowExpectedError[incompatible-exact]
132+
// $FlowExpectedError[incompatible-type]
131133
return new Event('custom', () => {});
132134
}).not.toThrow();
133135
});
@@ -238,15 +240,15 @@ describe('Event', () => {
238240

239241
it('should use a custom timestamp when set via setEventInitTimeStamp', () => {
240242
const customTimestamp = 12345.678;
241-
const options = {};
243+
const options: EventOptions = {};
242244
setEventInitTimeStamp(options, customTimestamp);
243245
const event = new Event('custom', options);
244246

245247
expect(event.timeStamp).toBe(customTimestamp);
246248
});
247249

248250
it('should accept zero as a valid custom timestamp', () => {
249-
const options = {};
251+
const options: EventOptions = {};
250252
setEventInitTimeStamp(options, 0);
251253
const event = new Event('custom', options);
252254

@@ -300,6 +302,7 @@ describe('Event', () => {
300302

301303
expect(event.defaultPrevented).toBe(false);
302304

305+
// $FlowFixMe[incompatible-type] The global is backed by this implementation.
303306
setInPassiveListenerFlag(event, true);
304307

305308
event.preventDefault();

‎packages/react-native/src/private/webapis/dom/events/__tests__/EventHandlerAttributes-itest.js‎

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,21 +12,21 @@
1212

1313
import '@react-native/fantom/src/setUpDefaultReactNativeEnvironment';
1414

15-
import type {EventCallback} from 'react-native/src/private/webapis/dom/events/EventTarget';
16-
17-
import Event from 'react-native/src/private/webapis/dom/events/Event';
1815
import {
1916
getEventHandlerAttribute,
2017
setEventHandlerAttribute,
2118
} from 'react-native/src/private/webapis/dom/events/EventHandlerAttributes';
22-
import EventTarget from 'react-native/src/private/webapis/dom/events/EventTarget';
19+
20+
type EventCallback = (event: Event) => void;
2321

2422
class EventTargetSubclass extends EventTarget {
2523
get oncustomevent(): EventCallback | null {
24+
// $FlowFixMe[incompatible-type] The globals are backed by these implementations.
2625
return getEventHandlerAttribute(this, 'customEvent');
2726
}
2827

2928
set oncustomevent(listener: ?EventCallback) {
29+
// $FlowFixMe[incompatible-type] The globals are backed by these implementations.
3030
setEventHandlerAttribute(this, 'customEvent', listener);
3131
}
3232
}

0 commit comments

Comments
 (0)