@samitouri / QOS-React-2 / commits / 9102719baa

Tidy up React Scope API (#19352)

Dominic Gannaway committed Jul 16, 2020 at 16:21 UTC 9102719baacb64738e9235bc80d3d7d9918cc74c
14 files changed +136 -172
packages/react-dom/src/events/__tests__/DOMModernPluginEventSystem-test.internal.js
+80 -85
@@ -2728,6 +2728,77 @@ describe('DOMModernPluginEventSystem', () => {
2728 document.body.removeChild(container2);
2729 });
2730
2731 + // @gate experimental
2732 + it('handle propagation of click events between disjointed comment roots', () => {
2733 + const buttonRef = React.createRef();
2734 + const divRef = React.createRef();
2735 + const log = [];
2736 + const setClick = ReactDOM.unstable_createEventHandle('click');
2737 + const setClickCapture = ReactDOM.unstable_createEventHandle(
2738 + 'click',
2739 + {capture: true},
2740 + );
2741 + const onClick = jest.fn(e => log.push(['bubble', e.currentTarget]));
2742 + const onClickCapture = jest.fn(e =>
2743 + log.push(['capture', e.currentTarget]),
2744 + );
2745 +
2746 + function Child() {
2747 + React.useEffect(() => {
2748 + const click1 = setClick(divRef.current, onClick);
2749 + const click2 = setClickCapture(divRef.current, onClickCapture);
2750 + return () => {
2751 + click1();
2752 + click2();
2753 + };
2754 + });
2755 +
2756 + return <div ref={divRef}>Click me!</div>;
2757 + }
2758 +
2759 + function Parent() {
2760 + React.useEffect(() => {
2761 + const click1 = setClick(buttonRef.current, onClick);
2762 + const click2 = setClickCapture(
2763 + buttonRef.current,
2764 + onClickCapture,
2765 + );
2766 + return () => {
2767 + click1();
2768 + click2();
2769 + };
2770 + });
2771 +
2772 + return <button ref={buttonRef} />;
2773 + }
2774 +
2775 + // We use a comment node here, then mount to it
2776 + const disjointedNode = document.createComment(
2777 + ' react-mount-point-unstable ',
2778 + );
2779 + ReactDOM.render(<Parent />, container);
2780 + Scheduler.unstable_flushAll();
2781 + buttonRef.current.appendChild(disjointedNode);
2782 + ReactDOM.render(<Child />, disjointedNode);
2783 + Scheduler.unstable_flushAll();
2784 +
2785 + const buttonElement = buttonRef.current;
2786 + dispatchClickEvent(buttonElement);
2787 + expect(onClick).toHaveBeenCalledTimes(1);
2788 + expect(onClickCapture).toHaveBeenCalledTimes(1);
2789 + expect(log[0]).toEqual(['capture', buttonElement]);
2790 + expect(log[1]).toEqual(['bubble', buttonElement]);
2791 +
2792 + const divElement = divRef.current;
2793 + dispatchClickEvent(divElement);
2794 + expect(onClick).toHaveBeenCalledTimes(3);
2795 + expect(onClickCapture).toHaveBeenCalledTimes(3);
2796 + expect(log[2]).toEqual(['capture', buttonElement]);
2797 + expect(log[3]).toEqual(['capture', divElement]);
2798 + expect(log[4]).toEqual(['bubble', divElement]);
2799 + expect(log[5]).toEqual(['bubble', buttonElement]);
2800 + });
2801 +
2802 describe('Compatibility with Scopes API', () => {
2803 beforeEach(() => {
2804 jest.resetModules();
@@ -2751,7 +2822,7 @@ describe('DOMModernPluginEventSystem', () => {
2822 const onClickCapture = jest.fn(e =>
2823 log.push(['capture', e.currentTarget]),
2824 );
2754 - const TestScope = React.unstable_createScope();
2825 + const TestScope = React.unstable_Scope;
2826 const setClick = ReactDOM.unstable_createEventHandle('click');
2827 const setClickCapture = ReactDOM.unstable_createEventHandle(
2828 'click',
@@ -2808,7 +2879,7 @@ describe('DOMModernPluginEventSystem', () => {
2879 const onClickCapture = jest.fn(e =>
2880 log.push(['capture', e.currentTarget]),
2881 );
2811 - const TestScope = React.unstable_createScope();
2882 + const TestScope = React.unstable_Scope;
2883 const setClick = ReactDOM.unstable_createEventHandle('click');
2884 const setClickCapture = ReactDOM.unstable_createEventHandle(
2885 'click',
@@ -2892,7 +2963,7 @@ describe('DOMModernPluginEventSystem', () => {
2963 it('should not handle the target being a dangling text node within a scope', () => {
2964 const clickEvent = jest.fn();
2965 const buttonRef = React.createRef();
2895 - const TestScope = React.unstable_createScope();
2966 + const TestScope = React.unstable_Scope;
2967 const setClick = ReactDOM.unstable_createEventHandle('click');
2968
2969 function Test() {
@@ -2924,8 +2995,8 @@ describe('DOMModernPluginEventSystem', () => {
2995 const buttonRef = React.createRef();
2996 const outerOnClick = jest.fn();
2997 const innerOnClick = jest.fn(e => e.stopPropagation());
2927 - const TestScope = React.unstable_createScope();
2928 - const TestScope2 = React.unstable_createScope();
2998 + const TestScope = React.unstable_Scope;
2999 + const TestScope2 = React.unstable_Scope;
3000 const setClick = ReactDOM.unstable_createEventHandle('click');
3001
3002 function Test() {
@@ -2966,8 +3037,8 @@ describe('DOMModernPluginEventSystem', () => {
3037 const buttonRef = React.createRef();
3038 const outerOnClick = jest.fn(e => e.stopPropagation());
3039 const innerOnClick = jest.fn();
2969 - const TestScope = React.unstable_createScope();
2970 - const TestScope2 = React.unstable_createScope();
3040 + const TestScope = React.unstable_Scope;
3041 + const TestScope2 = React.unstable_Scope;
3042 const setClick = ReactDOM.unstable_createEventHandle('click');
3043
3044 function Test() {
@@ -3007,8 +3078,8 @@ describe('DOMModernPluginEventSystem', () => {
3078 it('handle stopPropagation (inner and outer) correctly between scopes', () => {
3079 const buttonRef = React.createRef();
3080 const onClick = jest.fn(e => e.stopPropagation());
3010 - const TestScope = React.unstable_createScope();
3011 - const TestScope2 = React.unstable_createScope();
3081 + const TestScope = React.unstable_Scope;
3082 + const TestScope2 = React.unstable_Scope;
3083 const setClick = ReactDOM.unstable_createEventHandle('click');
3084
3085 function Test() {
@@ -3042,82 +3113,6 @@ describe('DOMModernPluginEventSystem', () => {
3113
3114 expect(onClick).toHaveBeenCalledTimes(1);
3115 });
3045 -
3046 - // @gate experimental
3047 - it('handle propagation of click events between disjointed comment roots', () => {
3048 - const buttonRef = React.createRef();
3049 - const divRef = React.createRef();
3050 - const log = [];
3051 - const setClick = ReactDOM.unstable_createEventHandle('click');
3052 - const setClickCapture = ReactDOM.unstable_createEventHandle(
3053 - 'click',
3054 - {capture: true},
3055 - );
3056 - const onClick = jest.fn(e =>
3057 - log.push(['bubble', e.currentTarget]),
3058 - );
3059 - const onClickCapture = jest.fn(e =>
3060 - log.push(['capture', e.currentTarget]),
3061 - );
3062 -
3063 - function Child() {
3064 - React.useEffect(() => {
3065 - const click1 = setClick(divRef.current, onClick);
3066 - const click2 = setClickCapture(
3067 - divRef.current,
3068 - onClickCapture,
3069 - );
3070 - return () => {
3071 - click1();
3072 - click2();
3073 - };
3074 - });
3075 -
3076 - return <div ref={divRef}>Click me!</div>;
3077 - }
3078 -
3079 - function Parent() {
3080 - React.useEffect(() => {
3081 - const click1 = setClick(buttonRef.current, onClick);
3082 - const click2 = setClickCapture(
3083 - buttonRef.current,
3084 - onClickCapture,
3085 - );
3086 - return () => {
3087 - click1();
3088 - click2();
3089 - };
3090 - });
3091 -
3092 - return <button ref={buttonRef} />;
3093 - }
3094 -
3095 - // We use a comment node here, then mount to it
3096 - const disjointedNode = document.createComment(
3097 - ' react-mount-point-unstable ',
3098 - );
3099 - ReactDOM.render(<Parent />, container);
3100 - Scheduler.unstable_flushAll();
3101 - buttonRef.current.appendChild(disjointedNode);
3102 - ReactDOM.render(<Child />, disjointedNode);
3103 - Scheduler.unstable_flushAll();
3104 -
3105 - const buttonElement = buttonRef.current;
3106 - dispatchClickEvent(buttonElement);
3107 - expect(onClick).toHaveBeenCalledTimes(1);
3108 - expect(onClickCapture).toHaveBeenCalledTimes(1);
3109 - expect(log[0]).toEqual(['capture', buttonElement]);
3110 - expect(log[1]).toEqual(['bubble', buttonElement]);
3111 -
3112 - const divElement = divRef.current;
3113 - dispatchClickEvent(divElement);
3114 - expect(onClick).toHaveBeenCalledTimes(3);
3115 - expect(onClickCapture).toHaveBeenCalledTimes(3);
3116 - expect(log[2]).toEqual(['capture', buttonElement]);
3117 - expect(log[3]).toEqual(['capture', divElement]);
3118 - expect(log[4]).toEqual(['bubble', divElement]);
3119 - expect(log[5]).toEqual(['bubble', buttonElement]);
3120 - });
3116 });
3117 });
3118 },
packages/react-dom/src/events/__tests__/DeprecatedDOMEventResponderSystem-test.internal.js
+1 -1
@@ -561,7 +561,7 @@ describe('DOMEventResponderSystem', () => {
561 it('the event responder onUnmount() function should fire using scopes', () => {
562 let onUnmountFired = 0;
563
564 - const TestScope = React.unstable_createScope();
564 + const TestScope = React.unstable_Scope;
565 const TestResponder = createEventResponder({
566 targetEventTypes: [],
567 onUnmount: () => {
packages/react-dom/src/server/ReactPartialRenderer.js
+25 -25
@@ -1109,6 +1109,31 @@ class ReactDOMServerRenderer {
1109 }
1110 }
1111 // eslint-disable-next-line-no-fallthrough
1112 + case REACT_SCOPE_TYPE: {
1113 + if (enableScopeAPI) {
1114 + const nextChildren = toArray(
1115 + ((nextChild: any): ReactElement).props.children,
1116 + );
1117 + const frame: Frame = {
1118 + type: null,
1119 + domNamespace: parentNamespace,
1120 + children: nextChildren,
1121 + childIndex: 0,
1122 + context: context,
1123 + footer: '',
1124 + };
1125 + if (__DEV__) {
1126 + ((frame: any): FrameDev).debugElementStack = [];
1127 + }
1128 + this.stack.push(frame);
1129 + return '';
1130 + }
1131 + invariant(
1132 + false,
1133 + 'ReactDOMServer does not yet support scope components.',
1134 + );
1135 + }
1136 + // eslint-disable-next-line-no-fallthrough
1137 default:
1138 break;
1139 }
@@ -1299,31 +1324,6 @@ class ReactDOMServerRenderer {
1324 this.stack.push(frame);
1325 return '';
1326 }
1302 - // eslint-disable-next-line-no-fallthrough
1303 - case REACT_SCOPE_TYPE: {
1304 - if (enableScopeAPI) {
1305 - const nextChildren = toArray(
1306 - ((nextChild: any): ReactElement).props.children,
1307 - );
1308 - const frame: Frame = {
1309 - type: null,
1310 - domNamespace: parentNamespace,
1311 - children: nextChildren,
1312 - childIndex: 0,
1313 - context: context,
1314 - footer: '',
1315 - };
1316 - if (__DEV__) {
1317 - ((frame: any): FrameDev).debugElementStack = [];
1318 - }
1319 - this.stack.push(frame);
1320 - return '';
1321 - }
1322 - invariant(
1323 - false,
1324 - 'ReactDOMServer does not yet support scope components.',
1325 - );
1326 - }
1327 }
1328 }
1329
packages/react-interactions/events/src/dom/__tests__/FocusWithin-test.internal.js
+1 -1
@@ -409,7 +409,7 @@ describe.each(table)('FocusWithin responder', hasPointerEvents => {
409
410 // @gate experimental
411 it('is called after a nested focused element is unmounted (with scope query)', () => {
412 - const TestScope = React.unstable_createScope();
412 + const TestScope = React.unstable_Scope;
413 const testScopeQuery = (type, props) => true;
414 let targetNodes;
415 let targetNode;
packages/react-interactions/events/src/dom/create-event-handle/__tests__/useFocusWithin-test.internal.js
+1 -1
@@ -415,7 +415,7 @@ describe.each(table)(`useFocus`, hasPointerEvents => {
415
416 // @gate experimental
417 it('is called after a nested focused element is unmounted (with scope query)', () => {
418 - const TestScope = React.unstable_createScope();
418 + const TestScope = React.unstable_Scope;
419 const testScopeQuery = (type, props) => true;
420 let targetNodes;
421 let targetNode;
packages/react-reconciler/src/ReactFiber.new.js
+5 -11
@@ -501,7 +501,11 @@ export function createFiberFromTypeAndProps(
501 return createFiberFromOffscreen(pendingProps, mode, lanes, key);
502 case REACT_LEGACY_HIDDEN_TYPE:
503 return createFiberFromLegacyHidden(pendingProps, mode, lanes, key);
504 -
504 + case REACT_SCOPE_TYPE:
505 + if (enableScopeAPI) {
506 + return createFiberFromScope(type, pendingProps, mode, lanes, key);
507 + }
508 + // eslint-disable-next-line no-fallthrough
509 default: {
510 if (typeof type === 'object' && type !== null) {
511 switch (type.$$typeof) {
@@ -539,16 +543,6 @@ export function createFiberFromTypeAndProps(
543 );
544 }
545 break;
542 - case REACT_SCOPE_TYPE:
543 - if (enableScopeAPI) {
544 - return createFiberFromScope(
545 - type,
546 - pendingProps,
547 - mode,
548 - lanes,
549 - key,
550 - );
551 - }
546 }
547 }
548 let info = '';
packages/react-reconciler/src/ReactFiber.old.js
+5 -11
@@ -496,7 +496,11 @@ export function createFiberFromTypeAndProps(
496 return createFiberFromOffscreen(pendingProps, mode, lanes, key);
497 case REACT_LEGACY_HIDDEN_TYPE:
498 return createFiberFromLegacyHidden(pendingProps, mode, lanes, key);
499 -
499 + case REACT_SCOPE_TYPE:
500 + if (enableScopeAPI) {
501 + return createFiberFromScope(type, pendingProps, mode, lanes, key);
502 + }
503 + // eslint-disable-next-line no-fallthrough
504 default: {
505 if (typeof type === 'object' && type !== null) {
506 switch (type.$$typeof) {
@@ -534,16 +538,6 @@ export function createFiberFromTypeAndProps(
538 );
539 }
540 break;
537 - case REACT_SCOPE_TYPE:
538 - if (enableScopeAPI) {
539 - return createFiberFromScope(
540 - type,
541 - pendingProps,
542 - mode,
543 - lanes,
544 - key,
545 - );
546 - }
541 }
542 }
543 let info = '';
packages/react-reconciler/src/__tests__/ReactScope-test.internal.js
+10 -10
@@ -43,7 +43,7 @@ describe('ReactScope', () => {
43 // @gate experimental
44 it('DO_NOT_USE_queryAllNodes() works as intended', () => {
45 const testScopeQuery = (type, props) => true;
46 - const TestScope = React.unstable_createScope();
46 + const TestScope = React.unstable_Scope;
47 const scopeRef = React.createRef();
48 const divRef = React.createRef();
49 const spanRef = React.createRef();
@@ -78,7 +78,7 @@ describe('ReactScope', () => {
78 // @gate experimental
79 it('DO_NOT_USE_queryAllNodes() provides the correct host instance', () => {
80 const testScopeQuery = (type, props) => type === 'div';
81 - const TestScope = React.unstable_createScope();
81 + const TestScope = React.unstable_Scope;
82 const scopeRef = React.createRef();
83 const divRef = React.createRef();
84 const spanRef = React.createRef();
@@ -125,7 +125,7 @@ describe('ReactScope', () => {
125 // @gate experimental
126 it('DO_NOT_USE_queryFirstNode() works as intended', () => {
127 const testScopeQuery = (type, props) => true;
128 - const TestScope = React.unstable_createScope();
128 + const TestScope = React.unstable_Scope;
129 const scopeRef = React.createRef();
130 const divRef = React.createRef();
131 const spanRef = React.createRef();
@@ -159,7 +159,7 @@ describe('ReactScope', () => {
159
160 // @gate experimental
161 it('containsNode() works as intended', () => {
162 - const TestScope = React.unstable_createScope();
162 + const TestScope = React.unstable_Scope;
163 const scopeRef = React.createRef();
164 const divRef = React.createRef();
165 const spanRef = React.createRef();
@@ -209,7 +209,7 @@ describe('ReactScope', () => {
209
210 // @gate experimental
211 it('scopes support server-side rendering and hydration', () => {
212 - const TestScope = React.unstable_createScope();
212 + const TestScope = React.unstable_Scope;
213 const scopeRef = React.createRef();
214 const divRef = React.createRef();
215 const spanRef = React.createRef();
@@ -241,7 +241,7 @@ describe('ReactScope', () => {
241 // @gate experimental
242 it('getChildContextValues() works as intended', () => {
243 const TestContext = React.createContext();
244 - const TestScope = React.unstable_createScope();
244 + const TestScope = React.unstable_Scope;
245 const scopeRef = React.createRef();
246
247 function Test({toggle}) {
@@ -273,7 +273,7 @@ describe('ReactScope', () => {
273 let resolve;
274 const promise = new Promise(resolvePromise => (resolve = resolvePromise));
275 const ref = React.createRef();
276 - const TestScope = React.unstable_createScope();
276 + const TestScope = React.unstable_Scope;
277 const scopeRef = React.createRef();
278 const testScopeQuery = (type, props) => true;
279
@@ -345,7 +345,7 @@ describe('ReactScope', () => {
345 // @gate experimental
346 it('DO_NOT_USE_queryAllNodes() works as intended', () => {
347 const testScopeQuery = (type, props) => true;
348 - const TestScope = React.unstable_createScope();
348 + const TestScope = React.unstable_Scope;
349 const scopeRef = React.createRef();
350 const divRef = React.createRef();
351 const spanRef = React.createRef();
@@ -382,7 +382,7 @@ describe('ReactScope', () => {
382 // @gate experimental
383 it('DO_NOT_USE_queryFirstNode() works as intended', () => {
384 const testScopeQuery = (type, props) => true;
385 - const TestScope = React.unstable_createScope();
385 + const TestScope = React.unstable_Scope;
386 const scopeRef = React.createRef();
387 const divRef = React.createRef();
388 const spanRef = React.createRef();
@@ -418,7 +418,7 @@ describe('ReactScope', () => {
418
419 // @gate experimental
420 it('containsNode() works as intended', () => {
421 - const TestScope = React.unstable_createScope();
421 + const TestScope = React.unstable_Scope;
422 const scopeRef = React.createRef();
423 const divRef = React.createRef();
424 const spanRef = React.createRef();
packages/react/index.classic.fb.js
+1 -1
@@ -54,7 +54,7 @@ export {
54 DEPRECATED_useResponder,
55 DEPRECATED_createResponder,
56 // enableScopeAPI
57 - unstable_createScope,
57 + unstable_Scope,
58 unstable_useOpaqueIdentifier,
59 // enableDebugTracing
60 unstable_DebugTracingMode,
packages/react/index.js
+1 -1
@@ -81,6 +81,6 @@ export {
81 DEPRECATED_useResponder,
82 DEPRECATED_createResponder,
83 unstable_createFundamental,
84 - unstable_createScope,
84 + unstable_Scope,
85 unstable_useOpaqueIdentifier,
86 } from './src/React';
packages/react/index.modern.fb.js
+1 -1
@@ -53,7 +53,7 @@ export {
53 DEPRECATED_useResponder,
54 DEPRECATED_createResponder,
55 // enableScopeAPI
56 - unstable_createScope,
56 + unstable_Scope,
57 unstable_useOpaqueIdentifier,
58 // enableDebugTracing
59 unstable_DebugTracingMode,
packages/react/src/React.js
+2 -2
@@ -16,6 +16,7 @@ import {
16 REACT_SUSPENSE_TYPE,
17 REACT_SUSPENSE_LIST_TYPE,
18 REACT_LEGACY_HIDDEN_TYPE,
19 + REACT_SCOPE_TYPE,
20 } from 'shared/ReactSymbols';
21
22 import {Component, PureComponent} from './ReactBaseClasses';
@@ -59,7 +60,6 @@ import {createMutableSource} from './ReactMutableSource';
60 import ReactSharedInternals from './ReactSharedInternals';
61 import {createFundamental} from './ReactFundamental';
62 import {createEventResponder} from './ReactEventResponder';
62 -import {createScope} from './ReactScope';
63
64 // TODO: Move this branching into the other module instead and just re-export.
65 const createElement = __DEV__ ? createElementWithValidation : createElementProd;
@@ -121,6 +121,6 @@ export {
121 // enableFundamentalAPI
122 createFundamental as unstable_createFundamental,
123 // enableScopeAPI
124 - createScope as unstable_createScope,
124 + REACT_SCOPE_TYPE as unstable_Scope,
125 useOpaqueIdentifier as unstable_useOpaqueIdentifier,
126 };
packages/react/src/ReactScope.js deleted
-20
@@ -1,20 +0,0 @@
1 -/**
2 - * Copyright (c) Facebook, Inc. and its affiliates.
3 - *
4 - * This source code is licensed under the MIT license found in the
5 - * LICENSE file in the root directory of this source tree.
6 - * @flow
7 - */
8 -
9 -import type {ReactScope} from 'shared/ReactTypes';
10 -import {REACT_SCOPE_TYPE} from 'shared/ReactSymbols';
11 -
12 -export function createScope(): ReactScope {
13 - const scopeComponent = {
14 - $$typeof: REACT_SCOPE_TYPE,
15 - };
16 - if (__DEV__) {
17 - Object.freeze(scopeComponent);
18 - }
19 - return scopeComponent;
20 -}
packages/shared/isValidElementType.js
+3 -2
@@ -26,6 +26,7 @@ import {
26 REACT_SERVER_BLOCK_TYPE,
27 REACT_LEGACY_HIDDEN_TYPE,
28 } from 'shared/ReactSymbols';
29 +import {enableScopeAPI} from './ReactFeatureFlags';
30
31 export default function isValidElementType(type: mixed) {
32 if (typeof type === 'string' || typeof type === 'function') {
@@ -40,7 +41,8 @@ export default function isValidElementType(type: mixed) {
41 type === REACT_STRICT_MODE_TYPE ||
42 type === REACT_SUSPENSE_TYPE ||
43 type === REACT_SUSPENSE_LIST_TYPE ||
43 - type === REACT_LEGACY_HIDDEN_TYPE
44 + type === REACT_LEGACY_HIDDEN_TYPE ||
45 + (enableScopeAPI && type === REACT_SCOPE_TYPE)
46 ) {
47 return true;
48 }
@@ -54,7 +56,6 @@ export default function isValidElementType(type: mixed) {
56 type.$$typeof === REACT_FORWARD_REF_TYPE ||
57 type.$$typeof === REACT_FUNDAMENTAL_TYPE ||
58 type.$$typeof === REACT_RESPONDER_TYPE ||
57 - type.$$typeof === REACT_SCOPE_TYPE ||
59 type.$$typeof === REACT_BLOCK_TYPE ||
60 type[(0: any)] === REACT_SERVER_BLOCK_TYPE
61 ) {