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

Add Batched Mode #15502

Merged
merged 4 commits into from
May 13, 2019
Merged
Show file tree
Hide file tree
Changes from 2 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
3 changes: 2 additions & 1 deletion packages/react-dom/src/client/ReactDOM.js
Original file line number Diff line number Diff line change
Expand Up @@ -366,7 +366,8 @@ function ReactRoot(
isConcurrent: boolean,
hydrate: boolean,
) {
const root = createContainer(container, isConcurrent, hydrate);
const isBatched = false;
const root = createContainer(container, isBatched, isConcurrent, hydrate);
this._internalRoot = root;
}
ReactRoot.prototype.render = function(
Expand Down
3 changes: 2 additions & 1 deletion packages/react-dom/src/fire/ReactFire.js
Original file line number Diff line number Diff line change
Expand Up @@ -372,7 +372,8 @@ function ReactRoot(
isConcurrent: boolean,
hydrate: boolean,
) {
const root = createContainer(container, isConcurrent, hydrate);
const isBatched = false;
const root = createContainer(container, isBatched, isConcurrent, hydrate);
this._internalRoot = root;
}
ReactRoot.prototype.render = function(
Expand Down
2 changes: 1 addition & 1 deletion packages/react-native-renderer/src/ReactFabric.js
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ const ReactFabric: ReactFabricType = {
if (!root) {
// TODO (bvaughn): If we decide to keep the wrapper component,
// We could create a wrapper for containerTag as well to reduce special casing.
root = createContainer(containerTag, false, false);
root = createContainer(containerTag, false, false, false);
roots.set(containerTag, root);
}
updateContainer(element, root, null, callback);
Expand Down
2 changes: 1 addition & 1 deletion packages/react-native-renderer/src/ReactNativeRenderer.js
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@ const ReactNativeRenderer: ReactNativeType = {
if (!root) {
// TODO (bvaughn): If we decide to keep the wrapper component,
// We could create a wrapper for containerTag as well to reduce special casing.
root = createContainer(containerTag, false, false);
root = createContainer(containerTag, false, false, false);
roots.set(containerTag, root);
}
updateContainer(element, root, null, callback);
Expand Down
175 changes: 131 additions & 44 deletions packages/react-noop-renderer/src/createReactNoop.js
Original file line number Diff line number Diff line change
Expand Up @@ -832,77 +832,160 @@ function createReactNoop(reconciler: Function, useMutation: boolean) {
return textInstance.text;
}

function getChildren(root) {
if (root) {
return root.children;
} else {
return null;
}
}

function getPendingChildren(root) {
if (root) {
return root.pendingChildren;
} else {
return null;
}
}

function getChildrenAsJSX(root) {
const children = childToJSX(getChildren(root), null);
if (children === null) {
return null;
}
if (Array.isArray(children)) {
return {
$$typeof: REACT_ELEMENT_TYPE,
type: REACT_FRAGMENT_TYPE,
key: null,
ref: null,
props: {children},
_owner: null,
_store: __DEV__ ? {} : undefined,
};
}
return children;
}

function getPendingChildrenAsJSX(root) {
const children = childToJSX(getChildren(root), null);
if (children === null) {
return null;
}
if (Array.isArray(children)) {
return {
$$typeof: REACT_ELEMENT_TYPE,
type: REACT_FRAGMENT_TYPE,
key: null,
ref: null,
props: {children},
_owner: null,
_store: __DEV__ ? {} : undefined,
};
}
return children;
}

let idCounter = 0;

const ReactNoop = {
_Scheduler: Scheduler,

getChildren(rootID: string = DEFAULT_ROOT_ID) {
const container = rootContainers.get(rootID);
if (container) {
return container.children;
} else {
return null;
}
return getChildren(container);
},

getPendingChildren(rootID: string = DEFAULT_ROOT_ID) {
const container = rootContainers.get(rootID);
if (container) {
return container.pendingChildren;
} else {
return null;
}
return getPendingChildren(container);
},

getOrCreateRootContainer(
rootID: string = DEFAULT_ROOT_ID,
isConcurrent: boolean = false,
isBatched: boolean,
isConcurrent: boolean,
) {
let root = roots.get(rootID);
if (!root) {
const container = {rootID: rootID, pendingChildren: [], children: []};
rootContainers.set(rootID, container);
root = NoopRenderer.createContainer(container, isConcurrent, false);
root = NoopRenderer.createContainer(
container,
isBatched,
isConcurrent,
false,
);
roots.set(rootID, root);
}
return root.current.stateNode.containerInfo;
},

// TODO: Replace ReactNoop.render with createRoot + root.render
createRoot() {
const isBatched = true;
const isConcurrent = true;
const container = {
rootID: '' + idCounter++,
pendingChildren: [],
children: [],
};
const fiberRoot = NoopRenderer.createContainer(
container,
isBatched,
isConcurrent,
false,
);
return {
_Scheduler: Scheduler,
render(children: ReactNodeList) {
NoopRenderer.updateContainer(children, fiberRoot, null, null);
},
getChildren() {
return getChildren(fiberRoot);
},
getChildrenAsJSX() {
return getChildrenAsJSX(fiberRoot);
},
};
},

createSyncRoot() {
const isBatched = true;
const isConcurrent = false;
const container = {
rootID: '' + idCounter++,
pendingChildren: [],
children: [],
};
const fiberRoot = NoopRenderer.createContainer(
container,
isBatched,
isConcurrent,
false,
);
return {
_Scheduler: Scheduler,
render(children: ReactNodeList) {
NoopRenderer.updateContainer(children, fiberRoot, null, null);
},
getChildren() {
return getChildren(container);
},
getChildrenAsJSX() {
return getChildrenAsJSX(container);
},
};
},

getChildrenAsJSX(rootID: string = DEFAULT_ROOT_ID) {
const children = childToJSX(ReactNoop.getChildren(rootID), null);
if (children === null) {
return null;
}
if (Array.isArray(children)) {
return {
$$typeof: REACT_ELEMENT_TYPE,
type: REACT_FRAGMENT_TYPE,
key: null,
ref: null,
props: {children},
_owner: null,
_store: __DEV__ ? {} : undefined,
};
}
return children;
const container = rootContainers.get(rootID);
return getChildrenAsJSX(container);
},

getPendingChildrenAsJSX(rootID: string = DEFAULT_ROOT_ID) {
const children = childToJSX(ReactNoop.getPendingChildren(rootID), null);
if (children === null) {
return null;
}
if (Array.isArray(children)) {
return {
$$typeof: REACT_ELEMENT_TYPE,
type: REACT_FRAGMENT_TYPE,
key: null,
ref: null,
props: {children},
_owner: null,
_store: __DEV__ ? {} : undefined,
};
}
return children;
const container = rootContainers.get(rootID);
return getPendingChildrenAsJSX(container);
},

createPortal(
Expand All @@ -920,9 +1003,11 @@ function createReactNoop(reconciler: Function, useMutation: boolean) {

renderLegacySyncRoot(element: React$Element<any>, callback: ?Function) {
const rootID = DEFAULT_ROOT_ID;
const isBatched = false;
const isConcurrent = false;
const container = ReactNoop.getOrCreateRootContainer(
rootID,
isBatched,
isConcurrent,
);
const root = roots.get(container.rootID);
Expand All @@ -934,9 +1019,11 @@ function createReactNoop(reconciler: Function, useMutation: boolean) {
rootID: string,
callback: ?Function,
) {
const isBatched = true;
const isConcurrent = true;
const container = ReactNoop.getOrCreateRootContainer(
rootID,
isBatched,
isConcurrent,
);
const root = roots.get(container.rootID);
Expand Down
59 changes: 22 additions & 37 deletions packages/react-reconciler/src/ReactFiber.js
Original file line number Diff line number Diff line change
Expand Up @@ -52,10 +52,11 @@ import getComponentName from 'shared/getComponentName';
import {isDevToolsPresent} from './ReactFiberDevToolsHook';
import {NoWork} from './ReactFiberExpirationTime';
import {
NoContext,
NoMode,
ConcurrentMode,
ProfileMode,
StrictMode,
BatchedMode,
} from './ReactTypeOfMode';
import {
REACT_FORWARD_REF_TYPE,
Expand Down Expand Up @@ -434,8 +435,18 @@ export function createWorkInProgress(
return workInProgress;
}

export function createHostRootFiber(isConcurrent: boolean): Fiber {
let mode = isConcurrent ? ConcurrentMode | StrictMode : NoContext;
export function createHostRootFiber(
isBatched: boolean,
isConcurrent: boolean,
): Fiber {
let mode;
if (isConcurrent) {
mode = ConcurrentMode | BatchedMode | StrictMode;
} else if (isBatched) {
mode = BatchedMode | StrictMode;
} else {
mode = NoMode;
}

if (enableProfilerTimer && isDevToolsPresent) {
// Always collect profile timings when DevTools are present.
Expand Down Expand Up @@ -476,19 +487,13 @@ export function createFiberFromTypeAndProps(
key,
);
case REACT_CONCURRENT_MODE_TYPE:
return createFiberFromMode(
pendingProps,
mode | ConcurrentMode | StrictMode,
expirationTime,
key,
);
fiberTag = Mode;
mode |= ConcurrentMode | BatchedMode | StrictMode;
break;
case REACT_STRICT_MODE_TYPE:
return createFiberFromMode(
pendingProps,
mode | StrictMode,
expirationTime,
key,
);
fiberTag = Mode;
mode |= StrictMode;
break;
case REACT_PROFILER_TYPE:
return createFiberFromProfiler(pendingProps, mode, expirationTime, key);
case REACT_SUSPENSE_TYPE:
Expand Down Expand Up @@ -672,26 +677,6 @@ function createFiberFromProfiler(
return fiber;
}

function createFiberFromMode(
pendingProps: any,
mode: TypeOfMode,
expirationTime: ExpirationTime,
key: null | string,
): Fiber {
const fiber = createFiber(Mode, pendingProps, key, mode);

// TODO: The Mode fiber shouldn't have a type. It has a tag.
const type =
(mode & ConcurrentMode) === NoContext
? REACT_STRICT_MODE_TYPE
: REACT_CONCURRENT_MODE_TYPE;
fiber.elementType = type;
fiber.type = type;

fiber.expirationTime = expirationTime;
return fiber;
}

export function createFiberFromSuspense(
pendingProps: any,
mode: TypeOfMode,
Expand Down Expand Up @@ -720,7 +705,7 @@ export function createFiberFromText(
}

export function createFiberFromHostInstanceForDeletion(): Fiber {
const fiber = createFiber(HostComponent, null, null, NoContext);
const fiber = createFiber(HostComponent, null, null, NoMode);
// TODO: These should not need a type.
fiber.elementType = 'DELETED';
fiber.type = 'DELETED';
Expand Down Expand Up @@ -751,7 +736,7 @@ export function assignFiberPropertiesInDEV(
if (target === null) {
// This Fiber's initial properties will always be overwritten.
// We only use a Fiber to ensure the same hidden class so DEV isn't slow.
target = createFiber(IndeterminateComponent, null, null, NoContext);
target = createFiber(IndeterminateComponent, null, null, NoMode);
}

// This is intentionally written as a list of all properties.
Expand Down
Loading