prepareForCommit returns info object to be passed resetAfterCommit

The DOM renderer assumes that resetAfterCommit is called after
prepareForCommit without any nested commits in between. That may not
be the case now that syncUpdates forces a nested update.

To address, this changes the type of prepareForCommit to return a value
which is later passed to resetAfterCommit.
This commit is contained in:
Andrew Clark
2016-12-29 10:39:24 -08:00
parent ce8c978d63
commit 79f01b2425
8 changed files with 30 additions and 26 deletions
+2
View File
@@ -1207,6 +1207,7 @@ src/renderers/shared/fiber/__tests__/ReactIncrementalScheduling-test.js
* can opt-in to deferred/animation scheduling inside componentDidMount/Update
* performs Task work even after time runs out
* does not perform animation work after time runs out
* can force synchronous updates with syncUpdates, even inside batchedUpdates
src/renderers/shared/fiber/__tests__/ReactIncrementalSideEffects-test.js
* can update child nodes of a host instance
@@ -1576,6 +1577,7 @@ src/renderers/shared/shared/__tests__/ReactUpdates-test.js
* unstable_batchedUpdates should return value from a callback
* unmounts and remounts a root in the same batch
* handles reentrant mounting in synchronous mode
* mounts and unmounts are sync even in a batch
src/renderers/shared/shared/__tests__/refs-destruction-test.js
* should remove refs when destroying the parent
+13 -11
View File
@@ -67,9 +67,10 @@ type HostContextDev = {
};
type HostContextProd = string;
type HostContext = HostContextDev | HostContextProd;
let eventsEnabled : ?boolean = null;
let selectionInformation : ?mixed = null;
type CommitInfo = {
eventsEnabled: boolean,
selectionInformation: mixed,
};
var ELEMENT_NODE_TYPE = 1;
var DOC_NODE_TYPE = 9;
@@ -137,17 +138,18 @@ var DOMRenderer = ReactFiberReconciler({
return getChildNamespace(parentNamespace, type);
},
prepareForCommit() : void {
eventsEnabled = ReactBrowserEventEmitter.isEnabled();
prepareForCommit() : CommitInfo {
const eventsEnabled = ReactBrowserEventEmitter.isEnabled();
ReactBrowserEventEmitter.setEnabled(false);
selectionInformation = ReactInputSelection.getSelectionInformation();
return {
eventsEnabled,
selectionInformation: ReactInputSelection.getSelectionInformation(),
};
},
resetAfterCommit() : void {
ReactInputSelection.restoreSelection(selectionInformation);
selectionInformation = null;
ReactBrowserEventEmitter.setEnabled(eventsEnabled);
eventsEnabled = null;
resetAfterCommit(commitInfo : CommitInfo) : void {
ReactInputSelection.restoreSelection(commitInfo.selectionInformation);
ReactBrowserEventEmitter.setEnabled(commitInfo.eventsEnabled);
},
createInstance(
@@ -66,8 +66,8 @@ if (__DEV__) {
var ReactDebugCurrentFiber = require('ReactDebugCurrentFiber');
}
module.exports = function<T, P, I, TI, C, CX>(
config : HostConfig<T, P, I, TI, C, CX>,
module.exports = function<T, P, I, TI, C, CX, CI>(
config : HostConfig<T, P, I, TI, C, CX, CI>,
hostContext : HostContext<C, CX>,
scheduleUpdate : (fiber : Fiber, priorityLevel : PriorityLevel) => void,
getPriorityContext : () => PriorityLevel,
@@ -33,8 +33,8 @@ var {
ContentReset,
} = require('ReactTypeOfSideEffect');
module.exports = function<T, P, I, TI, C, CX>(
config : HostConfig<T, P, I, TI, C, CX>,
module.exports = function<T, P, I, TI, C, CX, CI>(
config : HostConfig<T, P, I, TI, C, CX, CI>,
hostContext : HostContext<C, CX>,
captureError : (failedFiber : Fiber, error: Error) => ?Fiber
) {
@@ -46,8 +46,8 @@ if (__DEV__) {
var ReactDebugCurrentFiber = require('ReactDebugCurrentFiber');
}
module.exports = function<T, P, I, TI, C, CX>(
config : HostConfig<T, P, I, TI, C, CX>,
module.exports = function<T, P, I, TI, C, CX, CI>(
config : HostConfig<T, P, I, TI, C, CX, CI>,
hostContext : HostContext<C, CX>,
) {
const {
@@ -34,8 +34,8 @@ export type HostContext<C, CX> = {
resetHostContainer() : void,
};
module.exports = function<T, P, I, TI, C, CX>(
config : HostConfig<T, P, I, TI, C, CX>
module.exports = function<T, P, I, TI, C, CX, CI>(
config : HostConfig<T, P, I, TI, C, CX, CI>
) : HostContext<C, CX> {
const {
getChildHostContext,
@@ -43,7 +43,7 @@ export type Deadline = {
type OpaqueNode = Fiber;
export type HostConfig<T, P, I, TI, C, CX> = {
export type HostConfig<T, P, I, TI, C, CX, CI> = {
getRootHostContext(rootContainerInstance : C) : CX,
getChildHostContext(parentHostContext : CX, type : T) : CX,
@@ -69,8 +69,8 @@ export type HostConfig<T, P, I, TI, C, CX> = {
scheduleAnimationCallback(callback : () => void) : void,
scheduleDeferredCallback(callback : (deadline : Deadline) => void) : void,
prepareForCommit() : void,
resetAfterCommit() : void,
prepareForCommit() : CI,
resetAfterCommit(commitInfo : CI) : void,
useSyncScheduling ?: boolean,
};
@@ -100,7 +100,7 @@ getContextForSubtree._injectFiber(function(fiber : Fiber) {
parentContext;
});
module.exports = function<T, P, I, TI, C, CX>(config : HostConfig<T, P, I, TI, C, CX>) : Reconciler<C, I, TI> {
module.exports = function<T, P, I, TI, C, CX, CI>(config : HostConfig<T, P, I, TI, C, CX, CI>) : Reconciler<C, I, TI> {
var {
scheduleUpdate,
@@ -74,7 +74,7 @@ if (__DEV__) {
var timeHeuristicForUnitOfWork = 1;
module.exports = function<T, P, I, TI, C, CX>(config : HostConfig<T, P, I, TI, C, CX>) {
module.exports = function<T, P, I, TI, C, CX, CI>(config : HostConfig<T, P, I, TI, C, CX, CI>) {
const hostContext = ReactFiberHostContext(config);
const { popHostContainer, popHostContext, resetHostContainer } = hostContext;
const { beginWork, beginFailedWork } = ReactFiberBeginWork(
@@ -348,7 +348,7 @@ module.exports = function<T, P, I, TI, C, CX>(config : HostConfig<T, P, I, TI, C
firstEffect = finishedWork.firstEffect;
}
prepareForCommit();
const commitInfo = prepareForCommit();
// Commit all the side-effects within a tree. We'll do this in two passes.
// The first pass performs all the host insertions, updates, deletions and
@@ -369,7 +369,7 @@ module.exports = function<T, P, I, TI, C, CX>(config : HostConfig<T, P, I, TI, C
}
}
resetAfterCommit();
resetAfterCommit(commitInfo);
// In the second pass we'll perform all life-cycles and ref callbacks.
// Life-cycles happen as a separate pass so that all placements, updates,