Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
62 commits
Select commit Hold shift + click to select a range
624d5b5
[Much WIP. Very not working.] Refactor progressed work model
acdlite May 2, 2017
21eb29f
Hidden children
acdlite May 23, 2017
83ff51c
Re-implement begin phase for fragments
acdlite May 23, 2017
3c4718f
Re-implement begin phase for classes
acdlite May 24, 2017
c45954d
Better naming for resuming/resetting work
acdlite May 25, 2017
020e7a2
Transferring priority during the complete phase
acdlite May 25, 2017
b14433a
Before processing an update queue, clone from current if necessary
acdlite May 25, 2017
c05987c
Fix arguments passed to componentWillUpdate
acdlite May 25, 2017
17fa02e
Push context provider before getting context
acdlite May 25, 2017
7d64b2e
Avoid "previous current" work-in-progress scenario
acdlite May 25, 2017
75e8c04
Pass pending props as an argument to createWorkInProgress
acdlite May 29, 2017
0a62806
Fix wrong priority being reset in bailoutOnHiddenChildren
acdlite May 29, 2017
b7d7ad7
Don't bubble work priority from the current tree
acdlite May 30, 2017
c400969
Don't stash work-in-progress as progressed work if it's no longer valid
acdlite May 30, 2017
c0f6cf9
Allocate a single progressed work object per fiber pair
acdlite May 30, 2017
62b64c7
Check for a forcedUpdate before checking shouldComponentUpdate
acdlite May 30, 2017
9e3768a
Don't schedule an update effect when shouldComponentUpdate returns false
acdlite May 30, 2017
b0dc149
Deprioritize setState inside hidden subtrees
acdlite May 30, 2017
a191962
Set current owner before calling render method
acdlite May 30, 2017
299ff8f
Begin failed work at the same priority that the error was thrown
acdlite May 30, 2017
19a33f3
Clear pending props and state from failed work
acdlite May 30, 2017
6c5af09
Make the fiber root an effect list
acdlite May 30, 2017
0175d3a
Check if object is extensible instead of comparing to emptyObject
acdlite May 30, 2017
303641b
Set progressed work on both fibers
acdlite May 30, 2017
b2d3f7a
Re-implement begin phase for portals
acdlite May 30, 2017
f4fa99a
Warn if shouldComponentUpdate returns undefined
acdlite May 30, 2017
5e7c2fc
Never call componentWillReceiveProps for initial render
acdlite May 30, 2017
b5c980b
Module-style components can be context providers
acdlite May 30, 2017
1b8c460
Schedule class component effects after lifecycles are called
acdlite May 30, 2017
b85724b
Pass next props as argument to begin<TypeOfWork>Component functions
acdlite May 30, 2017
6971d79
Extract body of reconcile function into a separate function
acdlite May 30, 2017
4424615
Move pure begin phase functions out of constructor
acdlite May 30, 2017
20caa40
Re-implement begin phase for coroutines
acdlite May 31, 2017
5a34910
Use any instead of mixed type for props
acdlite May 31, 2017
bf2d145
Reset pending props at start of begin phase
acdlite May 31, 2017
7aefa2d
Re-implement begin phase for hydration
acdlite May 31, 2017
0e54237
Pass nextContext to componentWillUpdate
acdlite Jun 1, 2017
1d04ebe
Cancel work timer after a bailout
acdlite Jun 1, 2017
4174480
Run test script
acdlite Jun 1, 2017
9940c8a
Run prettier
acdlite Jun 1, 2017
53d9e0f
Fix lint
acdlite Jun 1, 2017
7571b0c
Add tests from #8716
acdlite Jun 1, 2017
b9160ba
Add invariant
acdlite Jun 1, 2017
a1a2e9e
shouldReuseContent should return false for text nodes
acdlite Jun 1, 2017
758aa3c
Fix Flow arity errors
acdlite Jun 1, 2017
9df490d
Update newestWork at end of beginWork
acdlite Jun 1, 2017
c76dacc
Only fork work if it's newer than the last commit
acdlite Jun 1, 2017
4577349
Remove invariant
acdlite Jun 2, 2017
6527bb3
Set instance variables before calling commit phase lifecycles
acdlite Jun 2, 2017
5e20db9
Use a fiber to stash progressed work
acdlite Jun 2, 2017
bf44b5a
Add extra invariants when bailing out on already progressed work
acdlite Jun 2, 2017
aa77ecf
Priority bubbling
acdlite Jun 6, 2017
7af9eae
Simulate Sierpinski triangle demo
acdlite Jun 6, 2017
2b38dc3
Change color of dots on each tick in triangle demo
acdlite Jun 6, 2017
6e94072
Add pendingWorkPriority to ProgressedWork
acdlite Jun 7, 2017
ec911db
Triangle tester: Simulate multiple hovers in a single step
acdlite Jun 7, 2017
9cec000
Add ReactNoop.yieldBeforeNextUnitOfWork() API
acdlite Jun 7, 2017
e1209b2
Use generator-based API for ReactNoop.yield
acdlite Jun 8, 2017
3a9069d
When comparing insertion positions, only compare non-null values
acdlite Jun 9, 2017
2b72ba2
Improve Triangle simulator
acdlite Jun 9, 2017
0959584
Fix argument order
acdlite Jun 10, 2017
32cb894
Introduce new failing test
acdlite Jun 10, 2017
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
12 changes: 9 additions & 3 deletions fixtures/fiber-triangle/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ <h1>Fiber Example</h1>
font: 'normal 15px sans-serif',
textAlign: 'center',
cursor: 'pointer',
color: 'white',
};

var containerStyle = {
Expand All @@ -40,6 +41,10 @@ <h1>Fiber Example</h1>

var targetSize = 25;

let dotCount = 0;

const colors = ['red', 'blue', 'green', 'orange', 'purple', 'black'];

class Dot extends React.Component {
constructor() {
super();
Expand All @@ -66,11 +71,12 @@ <h1>Fiber Example</h1>
top: (props.y) + 'px',
borderRadius: (s / 2) + 'px',
lineHeight: (s) + 'px',
background: this.state.hover ? '#ff0' : dotStyle.background
background: this.state.hover ? '#ff0' : colors[props.text % colors.length],
color: this.state.hover ? 'black' : dotStyle.color,
};
return (
<div style={style} onMouseEnter={() => this.enter()} onMouseLeave={() => this.leave()}>
{this.state.hover ? '*' + props.text + '*' : props.text}
<div ref={div => this.div = div} style={style} onMouseEnter={() => this.enter()} onMouseLeave={() => this.leave()}>
{this.state.hover ? `*${props.text}*` : props.text}
</div>
);
}
Expand Down
3 changes: 3 additions & 0 deletions scripts/fiber/tests-failing.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,6 @@ src/renderers/dom/shared/__tests__/ReactDOMServerIntegration-test.js
* should not blow away user-entered text on successful reconnect to a controlled checkbox
* should not blow away user-selected value on successful reconnect to an uncontrolled select
* should not blow away user-selected value on successful reconnect to an controlled select

src/renderers/shared/fiber/__tests__/ReactIncrementalTriangle-test.js
* resumes work by comparing the priority at which the work-in-progress was created/updated
6 changes: 0 additions & 6 deletions scripts/fiber/tests-passing-except-dev.txt
Original file line number Diff line number Diff line change
Expand Up @@ -86,12 +86,6 @@ src/renderers/dom/shared/__tests__/ReactDOMServerIntegration-test.js
* renders a div with a single child surrounded by whitespace with client render on top of bad server markup
* renders >,<, and & as single child with client render on top of bad server markup
* renders >,<, and & as multiple children with client render on top of bad server markup
* throws when rendering a string component with clean client render
* throws when rendering a string component with client render on top of bad server markup
* throws when rendering an undefined component with clean client render
* throws when rendering an undefined component with client render on top of bad server markup
* throws when rendering a number component with clean client render
* throws when rendering a number component with client render on top of bad server markup
* renders an input with a value and an onChange with client render on top of bad server markup
* renders an input with a value and readOnly with client render on top of bad server markup
* renders an input with a value and no onChange/readOnly with client render on top of bad server markup
Expand Down
11 changes: 11 additions & 0 deletions scripts/fiber/tests-passing.txt
Original file line number Diff line number Diff line change
Expand Up @@ -1121,8 +1121,14 @@ src/renderers/dom/shared/__tests__/ReactDOMServerIntegration-test.js
* renders >,<, and & as multiple children with clean client render
* renders >,<, and & as multiple children with client render on top of good server markup
* throws when rendering a string component with server string render
* throws when rendering a string component with clean client render
* throws when rendering a string component with client render on top of bad server markup
* throws when rendering an undefined component with server string render
* throws when rendering an undefined component with clean client render
* throws when rendering an undefined component with client render on top of bad server markup
* throws when rendering a number component with server string render
* throws when rendering a number component with clean client render
* throws when rendering a number component with client render on top of bad server markup
* throws when rendering null with server string render
* throws when rendering null with clean client render
* throws when rendering null with client render on top of bad server markup
Expand Down Expand Up @@ -1860,13 +1866,18 @@ src/renderers/shared/fiber/__tests__/ReactIncrementalSideEffects-test.js
* can defer side-effects and resume them later on
* can defer side-effects and reuse them later - complex
* deprioritizes setStates that happens within a deprioritized tree
* does not drop priority from a progressed subtree
* does not complete already completed work
* calls callback after update is flushed
* calls setState callback even if component bails out
* calls componentWillUnmount after a deletion, even if nested
* calls componentDidMount/Update after insertion/update
* invokes ref callbacks after insertion/update/unmount
* supports string refs

src/renderers/shared/fiber/__tests__/ReactIncrementalTriangle-test.js
* works

src/renderers/shared/fiber/__tests__/ReactIncrementalUpdates-test.js
* applies updates in order of priority
* applies updates with equal priority in insertion order
Expand Down
7 changes: 6 additions & 1 deletion src/renderers/__tests__/ReactComponent-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,12 @@ describe('ReactComponent', () => {
var instance = <div ref="badDiv" />;
expect(function() {
instance = ReactTestUtils.renderIntoDocument(instance);
}).toThrow();
}).toThrow(
'Only a ReactOwner can have refs. You might be adding a ref to a ' +
"component that was not created inside a component's `render` " +
'method, or you have multiple copies of React loaded (details: ' +
'https://fb.me/react-refs-must-have-owner).',
);
});

it('should warn when children are mutated during render', () => {
Expand Down
4 changes: 3 additions & 1 deletion src/renderers/dom/fiber/ReactDOMFiber.js
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,9 @@ function getReactRootElementInContainer(container: any) {

function shouldReuseContent(container) {
const rootElement = getReactRootElementInContainer(container);
return !!(rootElement && rootElement.getAttribute(ID_ATTRIBUTE_NAME));
return !!(rootElement &&
rootElement.nodeType === ELEMENT_NODE &&
rootElement.getAttribute(ID_ATTRIBUTE_NAME));
}

function shouldAutoFocusHostComponent(type: string, props: Props): boolean {
Expand Down
85 changes: 69 additions & 16 deletions src/renderers/noop/ReactNoop.js
Original file line number Diff line number Diff line change
Expand Up @@ -212,6 +212,40 @@ var rootContainers = new Map();
var roots = new Map();
var DEFAULT_ROOT_ID = '<default>';

let yieldBeforeNextUnitOfWork = false;
let yieldValue = null;

function* flushUnitsOfWork(n: number): Generator<mixed, void, void> {
var didStop = false;
while (!didStop && scheduledDeferredCallback !== null) {
var cb = scheduledDeferredCallback;
scheduledDeferredCallback = null;
yieldBeforeNextUnitOfWork = false;
yieldValue = null;
var unitsRemaining = n;
var didYield = false;
cb({
timeRemaining() {
if (yieldBeforeNextUnitOfWork) {
didYield = true;
return 0;
}
if (unitsRemaining-- > 0) {
return 999;
}
didStop = true;
return 0;
},
});

if (didYield) {
const valueToYield = yieldValue;
yieldValue = null;
yield valueToYield;
}
}
}

var ReactNoop = {
getChildren(rootID: string = DEFAULT_ROOT_ID) {
const container = rootContainers.get(rootID);
Expand Down Expand Up @@ -277,29 +311,48 @@ var ReactNoop = {
},

flushDeferredPri(timeout: number = Infinity) {
var cb = scheduledDeferredCallback;
if (cb === null) {
return;
// The legacy version of this function decremented the timeout before
// returning the new time.
// TODO: Convert tests to use flushUnitsOfWork or flushAndYield instead.
const n = timeout / 5 - 1;
const iterator = flushUnitsOfWork(n);
let value = iterator.next();
while (!value.done) {
value = iterator.next();
}
scheduledDeferredCallback = null;
var timeRemaining = timeout;
cb({
timeRemaining() {
// Simulate a fix amount of time progressing between each call.
timeRemaining -= 5;
if (timeRemaining < 0) {
timeRemaining = 0;
}
return timeRemaining;
},
});
// Don't flush animation priority in this legacy function. Some tests may
// still rely on this behavior.
},

flush() {
ReactNoop.flushAnimationPri();
ReactNoop.flushDeferredPri();
},

*flushAndYield(unitsOfWork: number = Infinity): Generator<mixed, void, void> {
for (const value of flushUnitsOfWork(unitsOfWork)) {
yield value;
}
ReactNoop.flushAnimationPri();
},

flushUnitsOfWork(n: number) {
const iterator = flushUnitsOfWork(n);
let value = iterator.next();
while (!value.done) {
value = iterator.next();
}
// TODO: We should always flush animation priority after flushing normal/low
// priority. Move this to flushUnitsOfWork generator once tests
// are converted.
ReactNoop.flushAnimationPri();
},

yield(value: mixed) {
yieldBeforeNextUnitOfWork = true;
yieldValue = value;
},

performAnimationWork(fn: Function) {
NoopRenderer.performWithPriority(AnimationPriority, fn);
},
Expand Down Expand Up @@ -377,7 +430,7 @@ var ReactNoop = {
if (fiber.updateQueue) {
logUpdateQueue(fiber.updateQueue, depth);
}
const childInProgress = fiber.progressedChild;
const childInProgress = fiber.progressedWork.child;
if (childInProgress && childInProgress !== fiber.child) {
log(
' '.repeat(depth + 1) + 'IN PROGRESS: ' + fiber.progressedPriority,
Expand Down
Loading