Skip to content

Commit

Permalink
WIP
Browse files Browse the repository at this point in the history
  • Loading branch information
trueadm committed Jul 8, 2020
1 parent 894bf01 commit 0b6afad
Show file tree
Hide file tree
Showing 3 changed files with 51 additions and 37 deletions.
2 changes: 1 addition & 1 deletion packages/react-dom/src/__tests__/ReactDOM-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ describe('ReactDOM', () => {
ReactTestUtils = require('react-dom/test-utils');
});

it('should bubble onSubmit', function() {
it.only('should bubble onSubmit', function() {
const container = document.createElement('div');

let count = 0;
Expand Down
11 changes: 4 additions & 7 deletions packages/react-dom/src/__tests__/ReactDOMEventListener-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -349,13 +349,10 @@ describe('ReactDOMEventListener', () => {
}),
);
// As of the modern event system refactor, we now support
// this on <img>. The reason for this, is because we now
// attach all media events to the "root" or "portal" in the
// capture phase, rather than the bubble phase. This allows
// us to assign less event listeners to individual elements,
// which also nicely allows us to support more without needing
// to add more individual code paths to support various
// events that do not bubble.
// this on <img>. The reason for this, is because we allow
// events to be attached to nodes regardless of if they
// necessary support them. This is a strange test, as this
// would never occur from normal browser behavior.
expect(handleImgLoadStart).toHaveBeenCalledTimes(1);

videoRef.current.dispatchEvent(
Expand Down
75 changes: 46 additions & 29 deletions packages/react-dom/src/events/DOMModernPluginEventSystem.js
Original file line number Diff line number Diff line change
Expand Up @@ -389,45 +389,61 @@ function getTargetForEvent(
return rootContainerElement;
}

function listenToReactPropEventDependency(
dependency: DOMTopLevelEventType,
capture: boolean,
rootContainerElement: Element,
targetElement?: Element,
): void {
const target = getTargetForEvent(
dependency,
rootContainerElement,
targetElement,
);
// This is temporary, we will remove this when introducing focusin/focusout
capture = dependency === TOP_FOCUS || dependency === TOP_BLUR;
listenToTopLevelEvent(dependency, target, PLUGIN_EVENT_SYSTEM, capture);
}

export function listenToReactPropEvent(
reactPropEvent: string,
rootContainerElement: Element,
targetElement?: Element,
): void {
const listenerMap = getEventListenerMap(rootContainerElement);
// For optimization, let's check if we have the registration name
// on the rootContainerElement.
if (listenerMap.has(reactPropEvent)) {
return;
}
// Add the registration name to the map, so we can avoid processing
// this React prop event again.
listenerMap.set(reactPropEvent, null);
const dependencies = registrationNameDependencies[reactPropEvent];
const dependenciesLength = dependencies.length;
// If the dependencies length is 1, that means we're not using a polyfill
// plugin like ChangeEventPlugin, BeforeInputPlugin, EnterLeavePlugin and
// SelectEventPlugin. SimpleEventPlugin always only has a single dependency.
// Given this, we know that we never need to apply capture phase event
// listeners to anything other than the SimpleEventPlugin.
const registrationCapturePhase =
isCaptureRegistrationName(reactPropEvent) && dependenciesLength === 1;

for (let i = 0; i < dependenciesLength; i++) {
const dependency = dependencies[i];
// plugin like ChangeEventPlugin, BeforeInputPlugin, EnterLeavePlugin
// and SelectEventPlugin. We always use the native bubble event phase for
// these plugins and emulate two phase event dispatching. SimpleEventPlugin
// always only has a single dependency and SimpleEventPlugin events also
// use either the native capture event phase or bubble event phase, there
// is no emulation (except for focus/blur, but that will be removed soon).
const isPolyfillEventPlugin = dependenciesLength !== 1;

const capture =
registrationCapturePhase ||
// This is temporary, we will remove this when introducing focusin/focusout
dependency === TOP_FOCUS ||
dependency === TOP_BLUR;

const target = getTargetForEvent(
dependency,
if (isPolyfillEventPlugin) {
const listenerMap = getEventListenerMap(rootContainerElement);
// For optimization, we register plugins on the listener map, so we
// don't need to check each of their dependencies each time.
if (!listenerMap.has(reactPropEvent)) {
listenerMap.set(reactPropEvent, null);
for (let i = 0; i < dependenciesLength; i++) {
listenToReactPropEventDependency(
dependencies[i],
false,
rootContainerElement,
targetElement,
);
}
}
} else {
const cature = isCaptureRegistrationName(reactPropEvent);
listenToReactPropEventDependency(
dependencies[0],
cature,
rootContainerElement,
targetElement,
);
listenToTopLevelEvent(dependency, target, PLUGIN_EVENT_SYSTEM, capture);
}
}

Expand Down Expand Up @@ -584,7 +600,7 @@ export function dispatchEventForPluginEventSystem(
) {
return;
}
if (targetInst !== null) {
if (targetInst !== null && targetContainer !== nativeEvent.target) {
// The below logic attempts to work out if we need to change
// the target fiber to a different ancestor. We had similar logic
// in the legacy event system, except the big difference between
Expand Down Expand Up @@ -704,7 +720,8 @@ export function accumulateSinglePhaseListeners(
const targetType = event.type;
// shouldEmulateTwoPhase is temporary till we can polyfill focus/blur to
// focusin/focusout.
const shouldEmulateTwoPhase = targetType === TOP_FOCUS || targetType === TOP_BLUR;
const shouldEmulateTwoPhase =
targetType === TOP_FOCUS || targetType === TOP_BLUR;

// Accumulate all instances and listeners via the target -> root path.
while (instance !== null) {
Expand Down

0 comments on commit 0b6afad

Please sign in to comment.