Skip to content

Commit 4d886bf

Browse files
rubennortemeta-codesync[bot]
authored andcommitted
Use global DOM types in Fantom tests
Summary: 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] Differential Revision: D120528709
1 parent 803c90a commit 4d886bf

19 files changed

Lines changed: 69 additions & 52 deletions

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

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -620,7 +620,7 @@ type EventInit = Event$Init;
620620

621621
// https://dom.spec.whatwg.org/#interface-event
622622
declare class Event {
623-
constructor(type: string, eventInitDict?: Event$Init): void;
623+
constructor(type: string, eventInitDict?: ?Event$Init): void;
624624
/**
625625
* Returns the type of event, e.g. "click", "hashchange", or "submit".
626626
*/
@@ -713,10 +713,17 @@ declare class Event {
713713
/** Non-standard. See Event.prototype.composed */
714714
readonly scoped: boolean;
715715

716+
cancelBubble: boolean;
717+
716718
/**
717719
* @deprecated
718720
*/
719721
initEvent(type: string, bubbles: boolean, cancelable: boolean): void;
722+
723+
static readonly NONE: 0;
724+
static readonly CAPTURING_PHASE: 1;
725+
static readonly AT_TARGET: 2;
726+
static readonly BUBBLING_PHASE: 3;
720727
}
721728

722729
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: 10 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 = EventInit & {
19+
rnIsDirect?: boolean,
20+
};
21+
1922
describe('Event', () => {
2023
it('provides read-only constants for event phases', () => {
2124
'use strict';
@@ -109,6 +112,7 @@ describe('Event', () => {
109112
);
110113

111114
expect(() => {
115+
// $FlowFixMe[incompatible-type] The React Native implementation accepts null.
112116
return new Event('custom', null);
113117
}).not.toThrow();
114118

@@ -121,13 +125,12 @@ describe('Event', () => {
121125
}).not.toThrow();
122126

123127
expect(() => {
124-
// $FlowExpectedError[incompatible-exact]
125-
// $FlowExpectedError[prop-missing]
128+
// $FlowExpectedError[incompatible-type]
126129
return new Event('custom', class {});
127130
}).not.toThrow();
128131

129132
expect(() => {
130-
// $FlowExpectedError[incompatible-exact]
133+
// $FlowExpectedError[incompatible-type]
131134
return new Event('custom', () => {});
132135
}).not.toThrow();
133136
});
@@ -238,15 +241,15 @@ describe('Event', () => {
238241

239242
it('should use a custom timestamp when set via setEventInitTimeStamp', () => {
240243
const customTimestamp = 12345.678;
241-
const options = {};
244+
const options: EventOptions = {};
242245
setEventInitTimeStamp(options, customTimestamp);
243246
const event = new Event('custom', options);
244247

245248
expect(event.timeStamp).toBe(customTimestamp);
246249
});
247250

248251
it('should accept zero as a valid custom timestamp', () => {
249-
const options = {};
252+
const options: EventOptions = {};
250253
setEventInitTimeStamp(options, 0);
251254
const event = new Event('custom', options);
252255

@@ -300,6 +303,7 @@ describe('Event', () => {
300303

301304
expect(event.defaultPrevented).toBe(false);
302305

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

305309
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)