Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adds more scaffolding for experimental event API #15112

Merged
merged 17 commits into from
Mar 20, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion packages/react-art/src/ReactARTHostConfig.js
Original file line number Diff line number Diff line change
Expand Up @@ -340,6 +340,10 @@ export function getChildHostContext() {
return NO_CONTEXT;
}

export function getChildHostContextForEvent() {
return NO_CONTEXT;
}

export const scheduleTimeout = setTimeout;
export const cancelTimeout = clearTimeout;
export const noTimeout = -1;
Expand Down Expand Up @@ -440,7 +444,7 @@ export function handleEventComponent(
}

export function handleEventTarget(
type: string,
type: Symbol | number,
props: Props,
internalInstanceHandle: Object,
) {
Expand Down
87 changes: 82 additions & 5 deletions packages/react-dom/src/client/ReactDOMHostConfig.js
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,12 @@ import dangerousStyleValue from '../shared/dangerousStyleValue';

import type {DOMContainer} from './ReactDOM';
import type {ReactEventResponder} from 'shared/ReactTypes';
import {
REACT_EVENT_COMPONENT_TYPE,
REACT_EVENT_TARGET_TYPE,
REACT_EVENT_TARGET_TOUCH_HIT,
} from 'shared/ReactSymbols';
import getElementFromTouchHitTarget from 'shared/getElementFromTouchHitTarget';

export type Type = string;
export type Props = {
Expand All @@ -65,6 +71,10 @@ export type PublicInstance = Element | Text;
type HostContextDev = {
namespace: string,
ancestorInfo: mixed,
eventData: null | {|
isEventComponent?: boolean,
isEventTarget?: boolean,
|},
};
type HostContextProd = string;
export type HostContext = HostContextDev | HostContextProd;
Expand All @@ -73,7 +83,11 @@ export type ChildSet = void; // Unused
export type TimeoutHandle = TimeoutID;
export type NoTimeout = -1;

import {enableSuspenseServerRenderer} from 'shared/ReactFeatureFlags';
import {
enableSuspenseServerRenderer,
enableEventAPI,
} from 'shared/ReactFeatureFlags';
import warning from 'shared/warning';

// Intentionally not named imports because Rollup would
// use dynamic dispatch for CommonJS interop named imports.
Expand Down Expand Up @@ -142,7 +156,7 @@ export function getRootHostContext(
if (__DEV__) {
const validatedTag = type.toLowerCase();
const ancestorInfo = updatedAncestorInfo(null, validatedTag);
return {namespace, ancestorInfo};
return {namespace, ancestorInfo, eventData: null};
}
return namespace;
}
Expand All @@ -159,12 +173,42 @@ export function getChildHostContext(
parentHostContextDev.ancestorInfo,
type,
);
return {namespace, ancestorInfo};
return {namespace, ancestorInfo, eventData: null};
}
const parentNamespace = ((parentHostContext: any): HostContextProd);
return getChildNamespace(parentNamespace, type);
}

export function getChildHostContextForEvent(
parentHostContext: HostContext,
type: Symbol | number,
): HostContext {
if (__DEV__) {
const parentHostContextDev = ((parentHostContext: any): HostContextDev);
const {namespace, ancestorInfo} = parentHostContextDev;
let eventData = null;

if (type === REACT_EVENT_COMPONENT_TYPE) {
eventData = {
isEventComponent: true,
isEventTarget: false,
};
} else if (type === REACT_EVENT_TARGET_TYPE) {
warning(
parentHostContextDev.eventData !== null &&
parentHostContextDev.eventData.isEventComponent,
'validateDOMNesting: React event targets must be direct children of event components.',
);
eventData = {
isEventComponent: false,
isEventTarget: true,
};
}
return {namespace, ancestorInfo, eventData};
}
return parentHostContext;
}

export function getPublicInstance(instance: Instance): * {
return instance;
}
Expand Down Expand Up @@ -296,6 +340,23 @@ export function createTextInstance(
if (__DEV__) {
const hostContextDev = ((hostContext: any): HostContextDev);
validateDOMNesting(null, text, hostContextDev.ancestorInfo);
if (enableEventAPI) {
const eventData = hostContextDev.eventData;
if (eventData !== null) {
warning(
!eventData.isEventComponent,
'validateDOMNesting: React event components cannot have text DOM nodes as children. ' +
'Wrap the child text "%s" in an element.',
text,
);
warning(
!eventData.isEventTarget,
'validateDOMNesting: React event targets cannot have text DOM nodes as children. ' +
'Wrap the child text "%s" in an element.',
text,
);
}
}
}
const textNode: TextInstance = createTextNode(text, rootContainerInstance);
precacheFiberNode(internalInstanceHandle, textNode);
Expand Down Expand Up @@ -804,9 +865,25 @@ export function handleEventComponent(
}

export function handleEventTarget(
type: string,
type: Symbol | number,
props: Props,
internalInstanceHandle: Object,
) {
// TODO: add handleEventTarget implementation
// Touch target hit slop handling
if (type === REACT_EVENT_TARGET_TOUCH_HIT) {
// Validates that there is a single element
const element = getElementFromTouchHitTarget(internalInstanceHandle);
if (element !== null) {
// We update the event target state node to be that of the element.
// We can then diff this entry to determine if we need to add the
// hit slop element, or change the dimensions of the hit slop.
const lastElement = internalInstanceHandle.stateNode;
if (lastElement !== element) {
internalInstanceHandle.stateNode = element;
// TODO: Create the hit slop element and attach it to the element
} else {
// TODO: Diff the left, top, right, bottom props
}
}
}
}
10 changes: 9 additions & 1 deletion packages/react-native-renderer/src/ReactFabricHostConfig.js
Original file line number Diff line number Diff line change
Expand Up @@ -283,6 +283,14 @@ export function getChildHostContext(
}
}

export function getChildHostContextForEvent(
parentHostContext: HostContext,
type: Symbol | number,
) {
// TODO: add getChildHostContextForEvent implementation
return parentHostContext;
}

export function getPublicInstance(instance: Instance): * {
return instance.canonical;
}
Expand Down Expand Up @@ -428,7 +436,7 @@ export function handleEventComponent(
}

export function handleEventTarget(
type: string,
type: Symbol | number,
props: Props,
internalInstanceHandle: Object,
) {
Expand Down
10 changes: 9 additions & 1 deletion packages/react-native-renderer/src/ReactNativeHostConfig.js
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,14 @@ export function getChildHostContext(
}
}

export function getChildHostContextForEvent(
parentHostContext: HostContext,
type: Symbol | number,
) {
// TODO: add getChildHostContextForEvent implementation
return parentHostContext;
}

export function getPublicInstance(instance: Instance): * {
return instance;
}
Expand Down Expand Up @@ -487,7 +495,7 @@ export function handleEventComponent(
}

export function handleEventTarget(
type: string,
type: Symbol | number,
props: Props,
internalInstanceHandle: Object,
) {
Expand Down
61 changes: 60 additions & 1 deletion packages/react-noop-renderer/src/createReactNoop.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,18 @@ import type {ReactNodeList} from 'shared/ReactTypes';
import * as Scheduler from 'scheduler/unstable_mock';
import {createPortal} from 'shared/ReactPortal';
import expect from 'expect';
import {REACT_FRAGMENT_TYPE, REACT_ELEMENT_TYPE} from 'shared/ReactSymbols';
import {
REACT_FRAGMENT_TYPE,
REACT_ELEMENT_TYPE,
REACT_EVENT_COMPONENT_TYPE,
REACT_EVENT_TARGET_TYPE,
REACT_EVENT_TARGET_TOUCH_HIT,
} from 'shared/ReactSymbols';
import warningWithoutStack from 'shared/warningWithoutStack';
import warning from 'shared/warning';
import getElementFromTouchHitTarget from 'shared/getElementFromTouchHitTarget';

import {enableEventAPI} from 'shared/ReactFeatureFlags';

// for .act's return value
type Thenable = {
Expand Down Expand Up @@ -54,6 +64,8 @@ type HostContext = Object;

const NO_CONTEXT = {};
const UPPERCASE_CONTEXT = {};
const EVENT_COMPONENT_CONTEXT = {};
const EVENT_TARGET_CONTEXT = {};
const UPDATE_SIGNAL = {};
if (__DEV__) {
Object.freeze(NO_CONTEXT);
Expand Down Expand Up @@ -250,6 +262,24 @@ function createReactNoop(reconciler: Function, useMutation: boolean) {
return NO_CONTEXT;
},

getChildHostContextForEvent(
parentHostContext: HostContext,
type: Symbol | number,
) {
if (__DEV__ && enableEventAPI) {
if (type === REACT_EVENT_COMPONENT_TYPE) {
return EVENT_COMPONENT_CONTEXT;
} else if (type === REACT_EVENT_TARGET_TYPE) {
warning(
parentHostContext === EVENT_COMPONENT_CONTEXT,
'validateDOMNesting: React event targets must be direct children of event components.',
);
return EVENT_TARGET_CONTEXT;
}
}
return parentHostContext;
},

getPublicInstance(instance) {
return instance;
},
Expand Down Expand Up @@ -333,6 +363,20 @@ function createReactNoop(reconciler: Function, useMutation: boolean) {
hostContext: Object,
internalInstanceHandle: Object,
): TextInstance {
if (__DEV__ && enableEventAPI) {
warning(
hostContext !== EVENT_COMPONENT_CONTEXT,
'validateDOMNesting: React event components cannot have text DOM nodes as children. ' +
'Wrap the child text "%s" in an element.',
text,
);
warning(
hostContext !== EVENT_TARGET_CONTEXT,
'validateDOMNesting: React event targets cannot have text DOM nodes as children. ' +
'Wrap the child text "%s" in an element.',
text,
);
}
if (hostContext === UPPERCASE_CONTEXT) {
text = text.toUpperCase();
}
Expand Down Expand Up @@ -363,6 +407,21 @@ function createReactNoop(reconciler: Function, useMutation: boolean) {

isPrimaryRenderer: true,
supportsHydration: false,

handleEventComponent() {
// NO-OP
},

handleEventTarget(
type: Symbol | number,
props: Props,
internalInstanceHandle: Object,
) {
if (type === REACT_EVENT_TARGET_TOUCH_HIT) {
// Validates that there is a single element
getElementFromTouchHitTarget(internalInstanceHandle);
}
},
};

const hostConfig = useMutation
Expand Down
Loading