Skip to content

Commit b1a0831

Browse files
authored
Revert legacy plugin modules (facebook#18638)
1 parent 31977d1 commit b1a0831

File tree

6 files changed

+233
-85
lines changed

6 files changed

+233
-85
lines changed

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

Lines changed: 202 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import type {Fiber} from 'react-reconciler/src/ReactInternalTypes';
1515
import type {PluginModule} from 'legacy-events/PluginModuleType';
1616
import type {ReactSyntheticEvent} from 'legacy-events/ReactSyntheticEventType';
1717
import type {TopLevelType} from 'legacy-events/TopLevelEventTypes';
18+
import forEachAccumulated from 'legacy-events/forEachAccumulated';
1819

1920
import {
2021
HostRoot,
@@ -45,6 +46,7 @@ import {
4546
} from './DOMTopLevelEventTypes';
4647
import {addTrappedEventListener} from './ReactDOMEventListener';
4748
import {batchedEventUpdates} from './ReactDOMUpdateBatching';
49+
import getListener from './getListener';
4850

4951
/**
5052
* Summary of `DOMEventPluginSystem` event handling:
@@ -396,3 +398,203 @@ export function legacyTrapCapturedEvent(
396398
);
397399
listenerMap.set(topLevelType, {passive: undefined, listener});
398400
}
401+
402+
function getParent(inst: Object | null): Object | null {
403+
if (!inst) {
404+
return null;
405+
}
406+
do {
407+
inst = inst.return;
408+
// TODO: If this is a HostRoot we might want to bail out.
409+
// That is depending on if we want nested subtrees (layers) to bubble
410+
// events to their parent. We could also go through parentNode on the
411+
// host node but that wouldn't work for React Native and doesn't let us
412+
// do the portal feature.
413+
} while (inst && inst.tag !== HostComponent);
414+
if (inst) {
415+
return inst;
416+
}
417+
return null;
418+
}
419+
420+
/**
421+
* Simulates the traversal of a two-phase, capture/bubble event dispatch.
422+
*/
423+
function traverseTwoPhase(
424+
inst: Object,
425+
fn: Function,
426+
arg: ReactSyntheticEvent,
427+
) {
428+
const path = [];
429+
while (inst) {
430+
path.push(inst);
431+
inst = getParent(inst);
432+
}
433+
let i;
434+
for (i = path.length; i-- > 0; ) {
435+
fn(path[i], 'captured', arg);
436+
}
437+
for (i = 0; i < path.length; i++) {
438+
fn(path[i], 'bubbled', arg);
439+
}
440+
}
441+
442+
function listenerAtPhase(inst, event, propagationPhase) {
443+
const registrationName =
444+
event.dispatchConfig.phasedRegistrationNames[propagationPhase];
445+
return getListener(inst, registrationName);
446+
}
447+
448+
/**
449+
* Return the lowest common ancestor of A and B, or null if they are in
450+
* different trees.
451+
*/
452+
export function getLowestCommonAncestor(
453+
instA: Object,
454+
instB: Object,
455+
): Object | null {
456+
let depthA = 0;
457+
for (let tempA = instA; tempA; tempA = getParent(tempA)) {
458+
depthA++;
459+
}
460+
let depthB = 0;
461+
for (let tempB = instB; tempB; tempB = getParent(tempB)) {
462+
depthB++;
463+
}
464+
465+
// If A is deeper, crawl up.
466+
while (depthA - depthB > 0) {
467+
instA = getParent(instA);
468+
depthA--;
469+
}
470+
471+
// If B is deeper, crawl up.
472+
while (depthB - depthA > 0) {
473+
instB = getParent(instB);
474+
depthB--;
475+
}
476+
477+
// Walk in lockstep until we find a match.
478+
let depth = depthA;
479+
while (depth--) {
480+
if (instA === instB || instA === instB.alternate) {
481+
return instA;
482+
}
483+
instA = getParent(instA);
484+
instB = getParent(instB);
485+
}
486+
return null;
487+
}
488+
489+
/**
490+
* Traverses the ID hierarchy and invokes the supplied `cb` on any IDs that
491+
* should would receive a `mouseEnter` or `mouseLeave` event.
492+
*
493+
* Does not invoke the callback on the nearest common ancestor because nothing
494+
* "entered" or "left" that element.
495+
*/
496+
export function traverseEnterLeave(
497+
from: Object,
498+
to: Object,
499+
fn: Function,
500+
argFrom: ReactSyntheticEvent,
501+
argTo: ReactSyntheticEvent,
502+
) {
503+
const common = from && to ? getLowestCommonAncestor(from, to) : null;
504+
const pathFrom = [];
505+
while (true) {
506+
if (!from) {
507+
break;
508+
}
509+
if (from === common) {
510+
break;
511+
}
512+
const alternate = from.alternate;
513+
if (alternate !== null && alternate === common) {
514+
break;
515+
}
516+
pathFrom.push(from);
517+
from = getParent(from);
518+
}
519+
const pathTo = [];
520+
while (true) {
521+
if (!to) {
522+
break;
523+
}
524+
if (to === common) {
525+
break;
526+
}
527+
const alternate = to.alternate;
528+
if (alternate !== null && alternate === common) {
529+
break;
530+
}
531+
pathTo.push(to);
532+
to = getParent(to);
533+
}
534+
for (let i = 0; i < pathFrom.length; i++) {
535+
fn(pathFrom[i], 'bubbled', argFrom);
536+
}
537+
for (let i = pathTo.length; i-- > 0; ) {
538+
fn(pathTo[i], 'captured', argTo);
539+
}
540+
}
541+
542+
function accumulateDirectionalDispatches(inst, phase, event) {
543+
if (__DEV__) {
544+
if (!inst) {
545+
console.error('Dispatching inst must not be null');
546+
}
547+
}
548+
const listener = listenerAtPhase(inst, event, phase);
549+
if (listener) {
550+
event._dispatchListeners = accumulateInto(
551+
event._dispatchListeners,
552+
listener,
553+
);
554+
event._dispatchInstances = accumulateInto(event._dispatchInstances, inst);
555+
}
556+
}
557+
558+
function accumulateTwoPhaseDispatchesSingle(event) {
559+
if (event && event.dispatchConfig.phasedRegistrationNames) {
560+
traverseTwoPhase(event._targetInst, accumulateDirectionalDispatches, event);
561+
}
562+
}
563+
564+
/**
565+
* Accumulates without regard to direction, does not look for phased
566+
* registration names. Same as `accumulateDirectDispatchesSingle` but without
567+
* requiring that the `dispatchMarker` be the same as the dispatched ID.
568+
*/
569+
function accumulateDispatches(
570+
inst: Object,
571+
ignoredDirection: ?boolean,
572+
event: Object,
573+
): void {
574+
if (inst && event && event.dispatchConfig.registrationName) {
575+
const registrationName = event.dispatchConfig.registrationName;
576+
const listener = getListener(inst, registrationName);
577+
if (listener) {
578+
event._dispatchListeners = accumulateInto(
579+
event._dispatchListeners,
580+
listener,
581+
);
582+
event._dispatchInstances = accumulateInto(event._dispatchInstances, inst);
583+
}
584+
}
585+
}
586+
587+
export function accumulateTwoPhaseDispatches(
588+
events: ReactSyntheticEvent | Array<ReactSyntheticEvent>,
589+
): void {
590+
forEachAccumulated(events, accumulateTwoPhaseDispatchesSingle);
591+
}
592+
593+
export function accumulateEnterLeaveDispatches(
594+
leave: ReactSyntheticEvent,
595+
enter: ReactSyntheticEvent,
596+
from: Fiber,
597+
to: Fiber,
598+
) {
599+
traverseEnterLeave(from, to, accumulateDispatches, leave, enter);
600+
}

packages/react-dom/src/events/plugins/LegacyBeforeInputEventPlugin.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ import {
2828
} from '../FallbackCompositionState';
2929
import SyntheticCompositionEvent from '../SyntheticCompositionEvent';
3030
import SyntheticInputEvent from '../SyntheticInputEvent';
31-
import accumulateTwoPhaseListeners from '../accumulateTwoPhaseListeners';
31+
import {accumulateTwoPhaseDispatches} from '../DOMLegacyEventPluginSystem';
3232

3333
const END_KEYCODES = [9, 13, 27, 32]; // Tab, Return, Esc, Space
3434
const START_KEYCODE = 229;
@@ -276,7 +276,7 @@ function extractCompositionEvent(
276276
}
277277
}
278278

279-
accumulateTwoPhaseListeners(event);
279+
accumulateTwoPhaseDispatches(event);
280280
return event;
281281
}
282282

@@ -437,7 +437,7 @@ function extractBeforeInputEvent(
437437
);
438438

439439
event.data = chars;
440-
accumulateTwoPhaseListeners(event);
440+
accumulateTwoPhaseDispatches(event);
441441
return event;
442442
}
443443

packages/react-dom/src/events/plugins/LegacyChangeEventPlugin.js

Lines changed: 4 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -27,13 +27,9 @@ import {updateValueIfChanged} from '../../client/inputValueTracking';
2727
import {setDefaultValue} from '../../client/ReactDOMInput';
2828
import {enqueueStateRestore} from '../ReactDOMControlledComponent';
2929

30-
import {
31-
disableInputAttributeSyncing,
32-
enableModernEventSystem,
33-
} from 'shared/ReactFeatureFlags';
34-
import accumulateTwoPhaseListeners from '../accumulateTwoPhaseListeners';
30+
import {disableInputAttributeSyncing} from 'shared/ReactFeatureFlags';
3531
import {batchedUpdates} from '../ReactDOMUpdateBatching';
36-
import {dispatchEventsInBatch} from '../DOMModernPluginEventSystem';
32+
import {accumulateTwoPhaseDispatches} from '../DOMLegacyEventPluginSystem';
3733

3834
const eventTypes = {
3935
change: {
@@ -64,7 +60,7 @@ function createAndAccumulateChangeEvent(inst, nativeEvent, target) {
6460
event.type = 'change';
6561
// Flag this event loop as needing state restore.
6662
enqueueStateRestore(target);
67-
accumulateTwoPhaseListeners(event);
63+
accumulateTwoPhaseDispatches(event);
6864
return event;
6965
}
7066
/**
@@ -105,11 +101,7 @@ function manualDispatchChangeEvent(nativeEvent) {
105101
}
106102

107103
function runEventInBatch(event) {
108-
if (enableModernEventSystem) {
109-
dispatchEventsInBatch([event]);
110-
} else {
111-
runEventsInBatch(event);
112-
}
104+
runEventsInBatch(event);
113105
}
114106

115107
function getInstIfValueChanged(targetInst) {

packages/react-dom/src/events/plugins/LegacyEnterLeaveEventPlugin.js

Lines changed: 17 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,7 @@ import {
2323
} from '../../client/ReactDOMComponentTree';
2424
import {HostComponent, HostText} from 'react-reconciler/src/ReactWorkTags';
2525
import {getNearestMountedFiber} from 'react-reconciler/src/ReactFiberTreeReflection';
26-
import {enableModernEventSystem} from 'shared/ReactFeatureFlags';
27-
import accumulateEnterLeaveListeners from '../accumulateEnterLeaveListeners';
26+
import {accumulateEnterLeaveDispatches} from '../DOMLegacyEventPluginSystem';
2827

2928
const eventTypes = {
3029
mouseEnter: {
@@ -67,26 +66,16 @@ const EnterLeaveEventPlugin = {
6766
const isOutEvent =
6867
topLevelType === TOP_MOUSE_OUT || topLevelType === TOP_POINTER_OUT;
6968

70-
if (isOverEvent && (eventSystemFlags & IS_REPLAYED) === 0) {
71-
const related = nativeEvent.relatedTarget || nativeEvent.fromElement;
72-
if (related) {
73-
if (enableModernEventSystem) {
74-
// Due to the fact we don't add listeners to the document with the
75-
// modern event system and instead attach listeners to roots, we
76-
// need to handle the over event case. To ensure this, we just need to
77-
// make sure the node that we're coming from is managed by React.
78-
const inst = getClosestInstanceFromNode(related);
79-
if (inst !== null) {
80-
return null;
81-
}
82-
} else {
83-
// If this is an over event with a target, then we've already dispatched
84-
// the event in the out event of the other target. If this is replayed,
85-
// then it's because we couldn't dispatch against this target previously
86-
// so we have to do it now instead.
87-
return null;
88-
}
89-
}
69+
if (
70+
isOverEvent &&
71+
(eventSystemFlags & IS_REPLAYED) === 0 &&
72+
(nativeEvent.relatedTarget || nativeEvent.fromElement)
73+
) {
74+
// If this is an over event with a target, then we've already dispatched
75+
// the event in the out event of the other target. If this is replayed,
76+
// then it's because we couldn't dispatch against this target previously
77+
// so we have to do it now instead.
78+
return null;
9079
}
9180

9281
if (!isOutEvent && !isOverEvent) {
@@ -174,15 +163,13 @@ const EnterLeaveEventPlugin = {
174163
enter.target = toNode;
175164
enter.relatedTarget = fromNode;
176165

177-
accumulateEnterLeaveListeners(leave, enter, from, to);
166+
accumulateEnterLeaveDispatches(leave, enter, from, to);
178167

179-
if (!enableModernEventSystem) {
180-
// If we are not processing the first ancestor, then we
181-
// should not process the same nativeEvent again, as we
182-
// will have already processed it in the first ancestor.
183-
if ((eventSystemFlags & IS_FIRST_ANCESTOR) === 0) {
184-
return [leave];
185-
}
168+
// If we are not processing the first ancestor, then we
169+
// should not process the same nativeEvent again, as we
170+
// will have already processed it in the first ancestor.
171+
if ((eventSystemFlags & IS_FIRST_ANCESTOR) === 0) {
172+
return [leave];
186173
}
187174

188175
return [leave, enter];

packages/react-dom/src/events/plugins/LegacySelectEventPlugin.js

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ import {getNodeFromInstance} from '../../client/ReactDOMComponentTree';
2626
import {hasSelectionCapabilities} from '../../client/ReactInputSelection';
2727
import {DOCUMENT_NODE} from '../../shared/HTMLNodeType';
2828
import {isListeningToAllDependencies} from '../DOMEventListenerMap';
29-
import accumulateTwoPhaseListeners from '../accumulateTwoPhaseListeners';
29+
import {accumulateTwoPhaseDispatches} from '../DOMLegacyEventPluginSystem';
3030

3131
const skipSelectionChangeEvent =
3232
canUseDOM && 'documentMode' in document && document.documentMode <= 11;
@@ -135,7 +135,7 @@ function constructSelectEvent(nativeEvent, nativeEventTarget) {
135135
syntheticEvent.type = 'select';
136136
syntheticEvent.target = activeElement;
137137

138-
accumulateTwoPhaseListeners(syntheticEvent);
138+
accumulateTwoPhaseDispatches(syntheticEvent);
139139

140140
return syntheticEvent;
141141
}
@@ -166,16 +166,11 @@ const SelectEventPlugin = {
166166
nativeEvent,
167167
nativeEventTarget,
168168
eventSystemFlags,
169-
container,
170169
) {
171-
const containerOrDoc =
172-
container || getEventTargetDocument(nativeEventTarget);
170+
const doc = getEventTargetDocument(nativeEventTarget);
173171
// Track whether all listeners exists for this plugin. If none exist, we do
174172
// not extract events. See #3639.
175-
if (
176-
!containerOrDoc ||
177-
!isListeningToAllDependencies('onSelect', containerOrDoc)
178-
) {
173+
if (!doc || !isListeningToAllDependencies('onSelect', doc)) {
179174
return null;
180175
}
181176

0 commit comments

Comments
 (0)