Skip to content

Commit 4279455

Browse files
authored
[Flare] Tweaks to Flare system design and API (#16264)
1 parent b5af4fe commit 4279455

39 files changed

+1143
-1193
lines changed

packages/react-debug-tools/src/ReactDebugHooks.js

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import type {
1111
ReactContext,
1212
ReactProviderType,
1313
ReactEventResponder,
14+
ReactEventResponderListener,
1415
} from 'shared/ReactTypes';
1516
import type {Fiber} from 'react-reconciler/src/ReactFiber';
1617
import type {Hook} from 'react-reconciler/src/ReactFiberHooks';
@@ -25,8 +26,6 @@ import {
2526
ForwardRef,
2627
} from 'shared/ReactWorkTags';
2728

28-
const emptyObject = {};
29-
3029
type CurrentDispatcherRef = typeof ReactSharedInternals.ReactCurrentDispatcher;
3130

3231
// Used to track hooks called during a render
@@ -221,17 +220,20 @@ function useMemo<T>(
221220
return value;
222221
}
223222

224-
function useListener(
223+
function useResponder(
225224
responder: ReactEventResponder<any, any>,
226-
hookProps: ?Object,
227-
): void {
228-
const listenerProps = hookProps || emptyObject;
225+
listenerProps: Object,
226+
): ReactEventResponderListener<any, any> {
229227
// Don't put the actual event responder object in, just its displayName
230228
const value = {
231229
responder: responder.displayName || 'EventResponder',
232230
props: listenerProps,
233231
};
234-
hookLog.push({primitive: 'Listener', stackError: new Error(), value});
232+
hookLog.push({primitive: 'Responder', stackError: new Error(), value});
233+
return {
234+
responder,
235+
props: listenerProps,
236+
};
235237
}
236238

237239
const Dispatcher: DispatcherType = {
@@ -246,7 +248,7 @@ const Dispatcher: DispatcherType = {
246248
useReducer,
247249
useRef,
248250
useState,
249-
useListener,
251+
useResponder,
250252
};
251253

252254
// Inspect

packages/react-debug-tools/src/__tests__/ReactHooksInspection-test.internal.js

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,19 +22,21 @@ describe('ReactHooksInspection', () => {
2222
ReactDebugTools = require('react-debug-tools');
2323
});
2424

25-
it('should inspect a simple useListener hook', () => {
25+
it('should inspect a simple useResponder hook', () => {
2626
const TestResponder = React.unstable_createResponder('TestResponder', {});
2727

2828
function Foo(props) {
29-
React.unstable_useListener(TestResponder, {preventDefault: false});
30-
return <div responders={<TestResponder />}>Hello world</div>;
29+
const listener = React.unstable_useResponder(TestResponder, {
30+
preventDefault: false,
31+
});
32+
return <div listeners={listener}>Hello world</div>;
3133
}
3234
let tree = ReactDebugTools.inspectHooks(Foo, {});
3335
expect(tree).toEqual([
3436
{
3537
isStateEditable: false,
3638
id: 0,
37-
name: 'Listener',
39+
name: 'Responder',
3840
value: {props: {preventDefault: false}, responder: 'TestResponder'},
3941
subHooks: [],
4042
},

packages/react-dom/src/client/ReactDOMComponent.js

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,7 @@ const AUTOFOCUS = 'autoFocus';
9898
const CHILDREN = 'children';
9999
const STYLE = 'style';
100100
const HTML = '__html';
101-
const RESPONDERS = 'responders';
101+
const LISTENERS = 'listeners';
102102

103103
const {html: HTML_NAMESPACE} = Namespaces;
104104

@@ -341,7 +341,7 @@ function setInitialDOMProperties(
341341
setTextContent(domElement, '' + nextProp);
342342
}
343343
} else if (
344-
(enableFlareAPI && propKey === RESPONDERS) ||
344+
(enableFlareAPI && propKey === LISTENERS) ||
345345
propKey === SUPPRESS_CONTENT_EDITABLE_WARNING ||
346346
propKey === SUPPRESS_HYDRATION_WARNING
347347
) {
@@ -698,7 +698,7 @@ export function diffProperties(
698698
} else if (propKey === DANGEROUSLY_SET_INNER_HTML || propKey === CHILDREN) {
699699
// Noop. This is handled by the clear text mechanism.
700700
} else if (
701-
(enableFlareAPI && propKey === RESPONDERS) ||
701+
(enableFlareAPI && propKey === LISTENERS) ||
702702
propKey === SUPPRESS_CONTENT_EDITABLE_WARNING ||
703703
propKey === SUPPRESS_HYDRATION_WARNING
704704
) {
@@ -790,7 +790,7 @@ export function diffProperties(
790790
(updatePayload = updatePayload || []).push(propKey, '' + nextProp);
791791
}
792792
} else if (
793-
(enableFlareAPI && propKey === RESPONDERS) ||
793+
(enableFlareAPI && propKey === LISTENERS) ||
794794
propKey === SUPPRESS_CONTENT_EDITABLE_WARNING ||
795795
propKey === SUPPRESS_HYDRATION_WARNING
796796
) {
@@ -1045,7 +1045,7 @@ export function diffHydratedProperties(
10451045
if (suppressHydrationWarning) {
10461046
// Don't bother comparing. We're ignoring all these warnings.
10471047
} else if (
1048-
(enableFlareAPI && propKey === RESPONDERS) ||
1048+
(enableFlareAPI && propKey === LISTENERS) ||
10491049
propKey === SUPPRESS_CONTENT_EDITABLE_WARNING ||
10501050
propKey === SUPPRESS_HYDRATION_WARNING ||
10511051
// Controlled attributes are not validated

packages/react-dom/src/events/DOMEventResponderSystem.js

Lines changed: 13 additions & 83 deletions
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,7 @@ import {
1212
PASSIVE_NOT_SUPPORTED,
1313
} from 'events/EventSystemFlags';
1414
import type {AnyNativeEvent} from 'events/PluginModuleType';
15-
import {
16-
HostComponent,
17-
FunctionComponent,
18-
MemoComponent,
19-
ForwardRef,
20-
} from 'shared/ReactWorkTags';
15+
import {HostComponent} from 'shared/ReactWorkTags';
2116
import type {EventPriority} from 'shared/ReactTypes';
2217
import type {
2318
ReactDOMEventResponder,
@@ -67,7 +62,7 @@ export function setListenToResponderEventTypes(
6762
}
6863

6964
type EventQueueItem = {|
70-
listeners: Array<(val: any) => void>,
65+
listener: (val: any) => void,
7166
value: any,
7267
|};
7368
type EventQueue = Array<EventQueueItem>;
@@ -103,24 +98,18 @@ let currentDocument: null | Document = null;
10398

10499
const eventResponderContext: ReactDOMResponderContext = {
105100
dispatchEvent(
106-
eventProp: string,
107101
eventValue: any,
102+
eventListener: any => void,
108103
eventPriority: EventPriority,
109104
): void {
110105
validateResponderContext();
111106
validateEventValue(eventValue);
112107
if (eventPriority < currentEventQueuePriority) {
113108
currentEventQueuePriority = eventPriority;
114109
}
115-
const responderInstance = ((currentInstance: any): ReactDOMEventResponderInstance);
116-
const target = responderInstance.fiber;
117-
const responder = responderInstance.responder;
118-
const listeners = collectListeners(eventProp, responder, target);
119-
if (listeners.length !== 0) {
120-
((currentEventQueue: any): EventQueue).push(
121-
createEventQueueItem(eventValue, listeners),
122-
);
123-
}
110+
((currentEventQueue: any): EventQueue).push(
111+
createEventQueueItem(eventValue, eventListener),
112+
);
124113
},
125114
isTargetWithinResponder(target: Element | Document): boolean {
126115
validateResponderContext();
@@ -392,11 +381,11 @@ function collectFocusableElements(
392381

393382
function createEventQueueItem(
394383
value: any,
395-
listeners: Array<(val: any) => void>,
384+
listener: (val: any) => void,
396385
): EventQueueItem {
397386
return {
398387
value,
399-
listeners,
388+
listener,
400389
};
401390
}
402391

@@ -519,70 +508,11 @@ function createDOMResponderEvent(
519508
};
520509
}
521510

522-
function collectListeners(
523-
eventProp: string,
524-
eventResponder: ReactDOMEventResponder,
525-
target: Fiber,
526-
): Array<(any) => void> {
527-
const eventListeners = [];
528-
let node = target.return;
529-
nodeTraversal: while (node !== null) {
530-
switch (node.tag) {
531-
case HostComponent: {
532-
const dependencies = node.dependencies;
533-
534-
if (dependencies !== null) {
535-
const respondersMap = dependencies.responders;
536-
537-
if (respondersMap !== null && respondersMap.has(eventResponder)) {
538-
break nodeTraversal;
539-
}
540-
}
541-
break;
542-
}
543-
case FunctionComponent:
544-
case MemoComponent:
545-
case ForwardRef: {
546-
const dependencies = node.dependencies;
547-
548-
if (dependencies !== null) {
549-
const listeners = dependencies.listeners;
550-
551-
if (listeners !== null) {
552-
for (
553-
let s = 0, listenersLength = listeners.length;
554-
s < listenersLength;
555-
s++
556-
) {
557-
const listener = listeners[s];
558-
const {responder, props} = listener;
559-
const listenerFunc = props[eventProp];
560-
561-
if (
562-
responder === eventResponder &&
563-
typeof listenerFunc === 'function'
564-
) {
565-
eventListeners.push(listenerFunc);
566-
}
567-
}
568-
}
569-
}
570-
}
571-
}
572-
node = node.return;
573-
}
574-
return eventListeners;
575-
}
576-
577511
function processEvents(eventQueue: EventQueue): void {
578512
for (let i = 0, length = eventQueue.length; i < length; i++) {
579-
const {value, listeners} = eventQueue[i];
580-
for (let s = 0, length2 = listeners.length; s < length2; s++) {
581-
const listener = listeners[s];
582-
const type =
583-
typeof value === 'object' && value !== null ? value.type : '';
584-
invokeGuardedCallbackAndCatchFirstError(type, listener, undefined, value);
585-
}
513+
const {value, listener} = eventQueue[i];
514+
const type = typeof value === 'object' && value !== null ? value.type : '';
515+
invokeGuardedCallbackAndCatchFirstError(type, listener, undefined, value);
586516
}
587517
}
588518

@@ -663,14 +593,14 @@ function traverseAndHandleEventResponderInstances(
663593
// - Bubble target responder phase
664594
// - Root responder phase
665595

596+
const visitedResponders = new Set();
666597
const responderEvent = createDOMResponderEvent(
667598
topLevelType,
668599
nativeEvent,
669600
nativeEventTarget,
670601
isPassiveEvent,
671602
isPassiveSupported,
672603
);
673-
const visitedResponders = new Set();
674604
let node = targetFiber;
675605
while (node !== null) {
676606
const {dependencies, tag} = node;
@@ -687,8 +617,8 @@ function traverseAndHandleEventResponderInstances(
687617
!visitedResponders.has(responder) &&
688618
validateResponderTargetEventTypes(eventType, responder)
689619
) {
690-
const onEvent = responder.onEvent;
691620
visitedResponders.add(responder);
621+
const onEvent = responder.onEvent;
692622
if (onEvent !== null) {
693623
currentInstance = responderInstance;
694624
responderEvent.responderTarget = ((target: any):

0 commit comments

Comments
 (0)