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

New API for top-level updates #10624

Closed
wants to merge 24 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
ae24a13
[Work-in-progress] Assign expiration times to updates
acdlite Aug 9, 2017
9a58ba2
Replace pendingWorkPriority with expiration times
acdlite Aug 10, 2017
6d1e2d8
Triangle Demo should use a class
acdlite Aug 11, 2017
383c50e
Use a magic value for task expiration time
acdlite Aug 11, 2017
466c746
Use current time to calculate expiration time
acdlite Aug 11, 2017
7900fed
Add unit tests for expiration and coalescing
acdlite Aug 11, 2017
a0df0b6
Delete unnecessary abstraction
acdlite Aug 11, 2017
4cd7cbe
Move performance.now polyfill to ReactDOMFrameScheduling
acdlite Aug 11, 2017
e26e737
Add expiration to fuzz tester
acdlite Aug 12, 2017
2bbd1c5
Expiration nits
acdlite Oct 8, 2017
70b82f7
Initial version of blocking & top-level resuming
acdlite Aug 18, 2017
3d5c12b
Change DOM renderer Container type to a union of String | DOMContainer
acdlite Aug 19, 2017
9154198
Split UpdateQueue functions to make it more generic
acdlite Aug 25, 2017
1fe313a
API for prerendering a top-level update and deferring the commit
acdlite Sep 6, 2017
792c810
Fix UpdateQueue flow types
acdlite Sep 6, 2017
4ea93cd
Completion callbacks resolve synchronously if tree is already complete
acdlite Sep 8, 2017
e73da46
renderer.create -> renderer.createRoot
acdlite Sep 8, 2017
d3fa711
Change optional type to optional parameter
acdlite Sep 8, 2017
14cf748
Process completion callbacks immediately after completing a root
acdlite Sep 9, 2017
e2abf2e
Add test for `then` resolving synchronously for sync updates
acdlite Sep 9, 2017
a4be91e
Committing a update on one root should not flush work on another root
acdlite Sep 11, 2017
a8f3335
Add hydration API
acdlite Sep 13, 2017
9a2ac61
Split scheduleUpdate into scheduleUpdate and scheduleWork.
acdlite Oct 4, 2017
9297052
Simplify top-level blockers
acdlite Oct 6, 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
81 changes: 42 additions & 39 deletions fixtures/fiber-triangle/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -76,51 +76,54 @@ <h1>Fiber Example</h1>
}
}

function SierpinskiTriangle({ x, y, s, children }) {
if (s <= targetSize) {
return (
<Dot
x={x - (targetSize / 2)}
y={y - (targetSize / 2)}
size={targetSize}
text={children}
/>
class SierpinskiTriangle extends React.Component {
shouldComponentUpdate(nextProps) {
var o = this.props;
var n = nextProps;
return !(
o.x === n.x &&
o.y === n.y &&
o.s === n.s &&
o.children === n.children
);
return r;
}
var newSize = s / 2;
var slowDown = true;
if (slowDown) {
var e = performance.now() + 0.8;
while (performance.now() < e) {
// Artificially long execution time.
render() {
let {x, y, s, children} = this.props;
if (s <= targetSize) {
return (
<Dot
x={x - (targetSize / 2)}
y={y - (targetSize / 2)}
size={targetSize}
text={children}
/>
);
return r;
}
var newSize = s / 2;
var slowDown = true;
if (slowDown) {
var e = performance.now() + 0.8;
while (performance.now() < e) {
// Artificially long execution time.
}
}
}

s /= 2;
s /= 2;

return [
<SierpinskiTriangle x={x} y={y - (s / 2)} s={s}>
{children}
</SierpinskiTriangle>,
<SierpinskiTriangle x={x - s} y={y + (s / 2)} s={s}>
{children}
</SierpinskiTriangle>,
<SierpinskiTriangle x={x + s} y={y + (s / 2)} s={s}>
{children}
</SierpinskiTriangle>,
];
return [
<SierpinskiTriangle x={x} y={y - (s / 2)} s={s}>
{children}
</SierpinskiTriangle>,
<SierpinskiTriangle x={x - s} y={y + (s / 2)} s={s}>
{children}
</SierpinskiTriangle>,
<SierpinskiTriangle x={x + s} y={y + (s / 2)} s={s}>
{children}
</SierpinskiTriangle>,
];
}
}
SierpinskiTriangle.shouldComponentUpdate = function(oldProps, newProps) {
var o = oldProps;
var n = newProps;
return !(
o.x === n.x &&
o.y === n.y &&
o.s === n.s &&
o.children === n.children
);
};

class ExampleApplication extends React.Component {
constructor() {
Expand Down
2 changes: 2 additions & 0 deletions src/renderers/art/ReactARTFiberEntry.js
Original file line number Diff line number Diff line change
Expand Up @@ -532,6 +532,8 @@ const ARTRenderer = ReactFiberReconciler({
);
},

now: ReactDOMFrameScheduling.now,

useSyncScheduling: true,
});

Expand Down
59 changes: 18 additions & 41 deletions src/renderers/dom/fiber/ReactDOMFiberComponent.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ var ReactDOMFiberOption = require('ReactDOMFiberOption');
var ReactDOMFiberSelect = require('ReactDOMFiberSelect');
var ReactDOMFiberTextarea = require('ReactDOMFiberTextarea');
var {getCurrentFiberOwnerName} = require('ReactDebugCurrentFiber');
var {DOCUMENT_NODE, DOCUMENT_FRAGMENT_NODE} = require('HTMLNodeType');

var assertValidProps = require('assertValidProps');
var emptyFunction = require('fbjs/lib/emptyFunction');
Expand Down Expand Up @@ -183,24 +182,6 @@ if (__DEV__) {
};
}

function ensureListeningTo(rootContainerElement, registrationName) {
var isDocumentOrFragment =
rootContainerElement.nodeType === DOCUMENT_NODE ||
rootContainerElement.nodeType === DOCUMENT_FRAGMENT_NODE;
var doc = isDocumentOrFragment
? rootContainerElement
: rootContainerElement.ownerDocument;
listenTo(registrationName, doc);
}

function getOwnerDocumentFromRootContainer(
rootContainerElement: Element | Document,
): Document {
return rootContainerElement.nodeType === DOCUMENT_NODE
? (rootContainerElement: any)
: rootContainerElement.ownerDocument;
}

// There are so many media events, it makes sense to just
// maintain a list rather than create a `trapBubbledEvent` for each
var mediaEvents = {
Expand Down Expand Up @@ -244,7 +225,7 @@ function trapClickOnNonInteractiveElement(node: HTMLElement) {

function setInitialDOMProperties(
domElement: Element,
rootContainerElement: Element | Document,
ownerDocument: Document,
nextProps: Object,
isCustomComponentTag: boolean,
): void {
Expand Down Expand Up @@ -284,7 +265,7 @@ function setInitialDOMProperties(
if (__DEV__ && typeof nextProp !== 'function') {
warnForInvalidEventListener(propKey, nextProp);
}
ensureListeningTo(rootContainerElement, propKey);
listenTo(propKey, ownerDocument);
}
} else if (isCustomComponentTag) {
DOMPropertyOperations.setValueForAttribute(domElement, propKey, nextProp);
Expand Down Expand Up @@ -338,14 +319,12 @@ var ReactDOMFiberComponent = {
createElement(
type: *,
props: Object,
rootContainerElement: Element | Document,
ownerDocument: Document,
parentNamespace: string,
): Element {
// We create tags in the namespace of their parent container, except HTML
// tags get no namespace.
var ownerDocument: Document = getOwnerDocumentFromRootContainer(
rootContainerElement,
);

var domElement: Element;
var namespaceURI = parentNamespace;
if (namespaceURI === HTML_NAMESPACE) {
Expand Down Expand Up @@ -408,17 +387,15 @@ var ReactDOMFiberComponent = {
return domElement;
},

createTextNode(text: string, rootContainerElement: Element | Document): Text {
return getOwnerDocumentFromRootContainer(
rootContainerElement,
).createTextNode(text);
createTextNode(text: string, ownerDocument: Document): Text {
return ownerDocument.createTextNode(text);
},

setInitialProperties(
domElement: Element,
tag: string,
rawProps: Object,
rootContainerElement: Element | Document,
ownerDocument: Document,
): void {
var isCustomComponentTag = isCustomComponent(tag, rawProps);
if (__DEV__) {
Expand Down Expand Up @@ -513,7 +490,7 @@ var ReactDOMFiberComponent = {
);
// For controlled components we always need to ensure we're listening
// to onChange. Even if there is no listener.
ensureListeningTo(rootContainerElement, 'onChange');
listenTo('onChange', ownerDocument);
break;
case 'option':
ReactDOMFiberOption.validateProps(domElement, rawProps);
Expand All @@ -529,7 +506,7 @@ var ReactDOMFiberComponent = {
);
// For controlled components we always need to ensure we're listening
// to onChange. Even if there is no listener.
ensureListeningTo(rootContainerElement, 'onChange');
listenTo('onChange', ownerDocument);
break;
case 'textarea':
ReactDOMFiberTextarea.initWrapperState(domElement, rawProps);
Expand All @@ -541,7 +518,7 @@ var ReactDOMFiberComponent = {
);
// For controlled components we always need to ensure we're listening
// to onChange. Even if there is no listener.
ensureListeningTo(rootContainerElement, 'onChange');
listenTo('onChange', ownerDocument);
break;
default:
props = rawProps;
Expand All @@ -551,7 +528,7 @@ var ReactDOMFiberComponent = {

setInitialDOMProperties(
domElement,
rootContainerElement,
ownerDocument,
props,
isCustomComponentTag,
);
Expand Down Expand Up @@ -590,7 +567,7 @@ var ReactDOMFiberComponent = {
tag: string,
lastRawProps: Object,
nextRawProps: Object,
rootContainerElement: Element | Document,
ownerDocument: Document,
): null | Array<mixed> {
if (__DEV__) {
validatePropertiesInDevelopment(tag, nextRawProps);
Expand Down Expand Up @@ -768,7 +745,7 @@ var ReactDOMFiberComponent = {
if (__DEV__ && typeof nextProp !== 'function') {
warnForInvalidEventListener(propKey, nextProp);
}
ensureListeningTo(rootContainerElement, propKey);
listenTo(propKey, ownerDocument);
}
if (!updatePayload && lastProp !== nextProp) {
// This is a special case. If any listener updates we need to ensure
Expand Down Expand Up @@ -835,7 +812,7 @@ var ReactDOMFiberComponent = {
tag: string,
rawProps: Object,
parentNamespace: string,
rootContainerElement: Element | Document,
ownerDocument: Document,
): null | Array<mixed> {
if (__DEV__) {
var suppressHydrationWarning =
Expand Down Expand Up @@ -924,7 +901,7 @@ var ReactDOMFiberComponent = {
);
// For controlled components we always need to ensure we're listening
// to onChange. Even if there is no listener.
ensureListeningTo(rootContainerElement, 'onChange');
listenTo('onChange', ownerDocument);
break;
case 'option':
ReactDOMFiberOption.validateProps(domElement, rawProps);
Expand All @@ -938,7 +915,7 @@ var ReactDOMFiberComponent = {
);
// For controlled components we always need to ensure we're listening
// to onChange. Even if there is no listener.
ensureListeningTo(rootContainerElement, 'onChange');
listenTo('onChange', ownerDocument);
break;
case 'textarea':
ReactDOMFiberTextarea.initWrapperState(domElement, rawProps);
Expand All @@ -949,7 +926,7 @@ var ReactDOMFiberComponent = {
);
// For controlled components we always need to ensure we're listening
// to onChange. Even if there is no listener.
ensureListeningTo(rootContainerElement, 'onChange');
listenTo('onChange', ownerDocument);
break;
}

Expand Down Expand Up @@ -1016,7 +993,7 @@ var ReactDOMFiberComponent = {
if (__DEV__ && typeof nextProp !== 'function') {
warnForInvalidEventListener(propKey, nextProp);
}
ensureListeningTo(rootContainerElement, propKey);
listenTo(propKey, ownerDocument);
}
} else if (__DEV__) {
// Validate that the properties correspond to their expected values.
Expand Down
Loading