Skip to content

Commit 2c4d61e

Browse files
authored
Adds experimental fundamental interface (#16049)
1 parent b4178af commit 2c4d61e

35 files changed

+898
-40
lines changed

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,7 @@
104104
"debug-test": "cross-env NODE_ENV=development node --inspect-brk node_modules/.bin/jest --config ./scripts/jest/config.source.js --runInBand",
105105
"test": "cross-env NODE_ENV=development jest --config ./scripts/jest/config.source.js",
106106
"test-persistent": "cross-env NODE_ENV=development jest --config ./scripts/jest/config.source-persistent.js",
107+
"debug-test-persistent": "cross-env NODE_ENV=development node --inspect-brk node_modules/.bin/jest --config ./scripts/jest/config.source-persistent.js --runInBand",
107108
"test-prod": "cross-env NODE_ENV=production jest --config ./scripts/jest/config.source.js",
108109
"test-prod-build": "yarn test-build-prod",
109110
"test-build": "cross-env NODE_ENV=development jest --config ./scripts/jest/config.build.js",

packages/react-art/src/ReactARTHostConfig.js

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -444,3 +444,23 @@ export function unmountEventComponent(
444444
): void {
445445
throw new Error('Not yet implemented.');
446446
}
447+
448+
export function getFundamentalComponentInstance(fundamentalInstance) {
449+
throw new Error('Not yet implemented.');
450+
}
451+
452+
export function mountFundamentalComponent(fundamentalInstance) {
453+
throw new Error('Not yet implemented.');
454+
}
455+
456+
export function shouldUpdateFundamentalComponent(fundamentalInstance) {
457+
throw new Error('Not yet implemented.');
458+
}
459+
460+
export function updateFundamentalComponent(fundamentalInstance) {
461+
throw new Error('Not yet implemented.');
462+
}
463+
464+
export function unmountFundamentalComponent(fundamentalInstance) {
465+
throw new Error('Not yet implemented.');
466+
}

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

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ import type {DOMContainer} from './ReactDOM';
4545
import type {
4646
ReactDOMEventResponder,
4747
ReactDOMEventComponentInstance,
48+
ReactDOMFundamentalComponentInstance,
4849
} from 'shared/ReactDOMTypes';
4950
import {
5051
addRootEventTypesForComponentInstance,
@@ -103,6 +104,7 @@ export type NoTimeout = -1;
103104
import {
104105
enableSuspenseServerRenderer,
105106
enableFlareAPI,
107+
enableFundamentalAPI,
106108
} from 'shared/ReactFeatureFlags';
107109
import warning from 'shared/warning';
108110

@@ -882,3 +884,65 @@ export function unmountEventComponent(
882884
unmountEventResponder(eventComponentInstance);
883885
}
884886
}
887+
888+
export function getFundamentalComponentInstance(
889+
fundamentalInstance: ReactDOMFundamentalComponentInstance,
890+
): Instance {
891+
if (enableFundamentalAPI) {
892+
const {currentFiber, impl, props, state} = fundamentalInstance;
893+
const instance = impl.getInstance(null, props, state);
894+
precacheFiberNode(currentFiber, instance);
895+
return instance;
896+
}
897+
// Because of the flag above, this gets around the Flow error;
898+
return (null: any);
899+
}
900+
901+
export function mountFundamentalComponent(
902+
fundamentalInstance: ReactDOMFundamentalComponentInstance,
903+
): void {
904+
if (enableFundamentalAPI) {
905+
const {impl, instance, props, state} = fundamentalInstance;
906+
const onMount = impl.onMount;
907+
if (onMount !== undefined) {
908+
onMount(null, instance, props, state);
909+
}
910+
}
911+
}
912+
913+
export function shouldUpdateFundamentalComponent(
914+
fundamentalInstance: ReactDOMFundamentalComponentInstance,
915+
): boolean {
916+
if (enableFundamentalAPI) {
917+
const {impl, prevProps, props, state} = fundamentalInstance;
918+
const shouldUpdate = impl.shouldUpdate;
919+
if (shouldUpdate !== undefined) {
920+
return shouldUpdate(null, prevProps, props, state);
921+
}
922+
}
923+
return true;
924+
}
925+
926+
export function updateFundamentalComponent(
927+
fundamentalInstance: ReactDOMFundamentalComponentInstance,
928+
): void {
929+
if (enableFundamentalAPI) {
930+
const {impl, instance, prevProps, props, state} = fundamentalInstance;
931+
const onUpdate = impl.onUpdate;
932+
if (onUpdate !== undefined) {
933+
onUpdate(null, instance, prevProps, props, state);
934+
}
935+
}
936+
}
937+
938+
export function unmountFundamentalComponent(
939+
fundamentalInstance: ReactDOMFundamentalComponentInstance,
940+
): void {
941+
if (enableFundamentalAPI) {
942+
const {impl, instance, props, state} = fundamentalInstance;
943+
const onUnmount = impl.onUnmount;
944+
if (onUnmount !== undefined) {
945+
onUnmount(null, instance, props, state);
946+
}
947+
}
948+
}

packages/react-dom/src/server/ReactPartialRenderer.js

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import {
2323
warnAboutDeprecatedLifecycles,
2424
enableSuspenseServerRenderer,
2525
enableFlareAPI,
26+
enableFundamentalAPI,
2627
} from 'shared/ReactFeatureFlags';
2728

2829
import {
@@ -39,6 +40,7 @@ import {
3940
REACT_LAZY_TYPE,
4041
REACT_MEMO_TYPE,
4142
REACT_EVENT_COMPONENT_TYPE,
43+
REACT_FUNDAMENTAL_TYPE,
4244
} from 'shared/ReactSymbols';
4345

4446
import {
@@ -1190,6 +1192,43 @@ class ReactDOMServerRenderer {
11901192
);
11911193
}
11921194
// eslint-disable-next-line-no-fallthrough
1195+
case REACT_FUNDAMENTAL_TYPE: {
1196+
if (enableFundamentalAPI) {
1197+
const fundamentalImpl = elementType.impl;
1198+
const open = fundamentalImpl.getServerSideString(
1199+
null,
1200+
nextElement.props,
1201+
);
1202+
const getServerSideStringClose =
1203+
fundamentalImpl.getServerSideStringClose;
1204+
const close =
1205+
getServerSideStringClose !== undefined
1206+
? getServerSideStringClose(null, nextElement.props)
1207+
: '';
1208+
const nextChildren =
1209+
fundamentalImpl.reconcileChildren !== false
1210+
? toArray(((nextChild: any): ReactElement).props.children)
1211+
: [];
1212+
const frame: Frame = {
1213+
type: null,
1214+
domNamespace: parentNamespace,
1215+
children: nextChildren,
1216+
childIndex: 0,
1217+
context: context,
1218+
footer: close,
1219+
};
1220+
if (__DEV__) {
1221+
((frame: any): FrameDev).debugElementStack = [];
1222+
}
1223+
this.stack.push(frame);
1224+
return open;
1225+
}
1226+
invariant(
1227+
false,
1228+
'ReactDOMServer does not yet support the fundamental API.',
1229+
);
1230+
}
1231+
// eslint-disable-next-line-no-fallthrough
11931232
case REACT_LAZY_TYPE:
11941233
invariant(
11951234
false,

packages/react-native-renderer/src/ReactFabricHostConfig.js

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -472,3 +472,27 @@ export function unmountEventComponent(
472472
unmountEventResponder(eventComponentInstance);
473473
}
474474
}
475+
476+
export function getFundamentalComponentInstance(fundamentalInstance) {
477+
throw new Error('Not yet implemented.');
478+
}
479+
480+
export function mountFundamentalComponent(fundamentalInstance) {
481+
throw new Error('Not yet implemented.');
482+
}
483+
484+
export function shouldUpdateFundamentalComponent(fundamentalInstance) {
485+
throw new Error('Not yet implemented.');
486+
}
487+
488+
export function updateFundamentalComponent(fundamentalInstance) {
489+
throw new Error('Not yet implemented.');
490+
}
491+
492+
export function unmountFundamentalComponent(fundamentalInstance) {
493+
throw new Error('Not yet implemented.');
494+
}
495+
496+
export function cloneFundamentalInstance(fundamentalInstance) {
497+
throw new Error('Not yet implemented.');
498+
}

packages/react-native-renderer/src/ReactNativeHostConfig.js

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -511,3 +511,23 @@ export function unmountEventComponent(
511511
): void {
512512
throw new Error('Not yet implemented.');
513513
}
514+
515+
export function getFundamentalComponentInstance(fundamentalInstance) {
516+
throw new Error('Not yet implemented.');
517+
}
518+
519+
export function mountFundamentalComponent(fundamentalInstance) {
520+
throw new Error('Not yet implemented.');
521+
}
522+
523+
export function shouldUpdateFundamentalComponent(fundamentalInstance) {
524+
throw new Error('Not yet implemented.');
525+
}
526+
527+
export function updateFundamentalComponent(fundamentalInstance) {
528+
throw new Error('Not yet implemented.');
529+
}
530+
531+
export function unmountFundamentalComponent(fundamentalInstance) {
532+
throw new Error('Not yet implemented.');
533+
}

packages/react-noop-renderer/src/createReactNoop.js

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -407,6 +407,57 @@ function createReactNoop(reconciler: Function, useMutation: boolean) {
407407
unmountEventComponent(): void {
408408
// NO-OP
409409
},
410+
411+
getFundamentalComponentInstance(fundamentalInstance): Instance {
412+
const {impl, props, state} = fundamentalInstance;
413+
return impl.getInstance(null, props, state);
414+
},
415+
416+
mountFundamentalComponent(fundamentalInstance): void {
417+
const {impl, instance, props, state} = fundamentalInstance;
418+
const onMount = impl.onUpdate;
419+
if (onMount !== undefined) {
420+
onMount(null, instance, props, state);
421+
}
422+
},
423+
424+
shouldUpdateFundamentalComponent(fundamentalInstance): boolean {
425+
const {impl, instance, prevProps, props, state} = fundamentalInstance;
426+
const shouldUpdate = impl.shouldUpdate;
427+
if (shouldUpdate !== undefined) {
428+
return shouldUpdate(null, instance, prevProps, props, state);
429+
}
430+
return true;
431+
},
432+
433+
updateFundamentalComponent(fundamentalInstance): void {
434+
const {impl, instance, prevProps, props, state} = fundamentalInstance;
435+
const onUpdate = impl.onUpdate;
436+
if (onUpdate !== undefined) {
437+
onUpdate(null, instance, prevProps, props, state);
438+
}
439+
},
440+
441+
unmountFundamentalComponent(fundamentalInstance): void {
442+
const {impl, instance, props, state} = fundamentalInstance;
443+
const onUnmount = impl.onUnmount;
444+
if (onUnmount !== undefined) {
445+
onUnmount(null, instance, props, state);
446+
}
447+
},
448+
449+
cloneFundamentalInstance(fundamentalInstance): Instance {
450+
const instance = fundamentalInstance.instance;
451+
return {
452+
children: [],
453+
text: instance.text,
454+
type: instance.type,
455+
prop: instance.prop,
456+
id: instance.id,
457+
context: instance.context,
458+
hidden: instance.hidden,
459+
};
460+
},
410461
};
411462

412463
const hostConfig = useMutation

packages/react-reconciler/src/ReactFiber.js

Lines changed: 34 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import type {
1313
ReactPortal,
1414
RefObject,
1515
ReactEventComponent,
16+
ReactFundamentalComponent,
1617
} from 'shared/ReactTypes';
1718
import type {RootTag} from 'shared/ReactRootTags';
1819
import type {WorkTag} from 'shared/ReactWorkTags';
@@ -26,7 +27,11 @@ import type {ReactEventComponentInstance} from 'shared/ReactTypes';
2627

2728
import invariant from 'shared/invariant';
2829
import warningWithoutStack from 'shared/warningWithoutStack';
29-
import {enableProfilerTimer, enableFlareAPI} from 'shared/ReactFeatureFlags';
30+
import {
31+
enableProfilerTimer,
32+
enableFlareAPI,
33+
enableFundamentalAPI,
34+
} from 'shared/ReactFeatureFlags';
3035
import {NoEffect, Placement} from 'shared/ReactSideEffectTags';
3136
import {ConcurrentRoot, BatchedRoot} from 'shared/ReactRootTags';
3237
import {
@@ -49,6 +54,7 @@ import {
4954
SimpleMemoComponent,
5055
LazyComponent,
5156
EventComponent,
57+
FundamentalComponent,
5258
} from 'shared/ReactWorkTags';
5359
import getComponentName from 'shared/getComponentName';
5460

@@ -79,6 +85,7 @@ import {
7985
REACT_MEMO_TYPE,
8086
REACT_LAZY_TYPE,
8187
REACT_EVENT_COMPONENT_TYPE,
88+
REACT_FUNDAMENTAL_TYPE,
8289
} from 'shared/ReactSymbols';
8390

8491
let hasBadMapPolyfill;
@@ -663,6 +670,17 @@ export function createFiberFromTypeAndProps(
663670
);
664671
}
665672
break;
673+
case REACT_FUNDAMENTAL_TYPE:
674+
if (enableFundamentalAPI) {
675+
return createFiberFromFundamental(
676+
type,
677+
pendingProps,
678+
mode,
679+
expirationTime,
680+
key,
681+
);
682+
}
683+
break;
666684
}
667685
}
668686
let info = '';
@@ -742,7 +760,7 @@ export function createFiberFromFragment(
742760
}
743761

744762
export function createFiberFromEventComponent(
745-
eventComponent: ReactEventComponent<any>,
763+
eventComponent: ReactEventComponent<any, any, any>,
746764
pendingProps: any,
747765
mode: TypeOfMode,
748766
expirationTime: ExpirationTime,
@@ -755,6 +773,20 @@ export function createFiberFromEventComponent(
755773
return fiber;
756774
}
757775

776+
export function createFiberFromFundamental(
777+
fundamentalComponent: ReactFundamentalComponent<any, any>,
778+
pendingProps: any,
779+
mode: TypeOfMode,
780+
expirationTime: ExpirationTime,
781+
key: null | string,
782+
): Fiber {
783+
const fiber = createFiber(FundamentalComponent, pendingProps, key, mode);
784+
fiber.elementType = fundamentalComponent;
785+
fiber.type = fundamentalComponent;
786+
fiber.expirationTime = expirationTime;
787+
return fiber;
788+
}
789+
758790
function createFiberFromProfiler(
759791
pendingProps: any,
760792
mode: TypeOfMode,

0 commit comments

Comments
 (0)