mirror of
https://github.com/facebook/react.git
synced 2025-11-01 09:12:30 +00:00
* Don't call idle callback unless there's time remaining * Expiration fixture Fixture that demonstrates how async work expires after a certain interval. The fixture clogs the main thread with animation work, so it only works if the `timeout` option is provided to `requestIdleCallback`. * Pass timeout option to requestIdleCallback Forces `requestIdleCallback` to fire if too much time has elapsed, even if the main thread is busy. Required to make expiration times work properly. Otherwise, async work can expire, but React never has a chance to flush it because the browser never calls into React.
246 lines
5.5 KiB
JavaScript
246 lines
5.5 KiB
JavaScript
/**
|
|
* Copyright (c) 2013-present, Facebook, Inc.
|
|
*
|
|
* This source code is licensed under the MIT license found in the
|
|
* LICENSE file in the root directory of this source tree.
|
|
*
|
|
* @flow
|
|
*/
|
|
|
|
import ReactFiberReconciler from 'react-reconciler';
|
|
import emptyObject from 'fbjs/lib/emptyObject';
|
|
import invariant from 'fbjs/lib/invariant';
|
|
// Module provided by RN:
|
|
import RTManager from 'RTManager';
|
|
|
|
import {
|
|
precacheFiberNode,
|
|
updateFiberProps,
|
|
} from './ReactNativeRTComponentTree';
|
|
import ReactNativeRTTagHandles from './ReactNativeRTTagHandles';
|
|
|
|
export type Container = number;
|
|
export type Instance = number;
|
|
export type Props = Object;
|
|
export type TextInstance = number;
|
|
|
|
function processProps(instance: number, props: Props): Object {
|
|
const propsPayload = {};
|
|
for (var key in props) {
|
|
if (key === 'children') {
|
|
// Skip special case.
|
|
continue;
|
|
}
|
|
var value = props[key];
|
|
if (typeof value === 'function') {
|
|
value = {
|
|
style: 'rt-event',
|
|
event: key,
|
|
tag: instance,
|
|
};
|
|
}
|
|
propsPayload[key] = value;
|
|
}
|
|
return propsPayload;
|
|
}
|
|
|
|
function arePropsEqual(oldProps: Props, newProps: Props): boolean {
|
|
var key;
|
|
for (key in newProps) {
|
|
if (key === 'children') {
|
|
// Skip special case.
|
|
continue;
|
|
}
|
|
if (newProps[key] !== oldProps[key]) {
|
|
return false;
|
|
}
|
|
}
|
|
for (key in oldProps) {
|
|
if (key === 'children') {
|
|
// Skip special case.
|
|
continue;
|
|
}
|
|
if (!(key in newProps)) {
|
|
return false;
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
const NativeRTRenderer = ReactFiberReconciler({
|
|
appendInitialChild(
|
|
parentInstance: Instance,
|
|
child: Instance | TextInstance,
|
|
): void {
|
|
RTManager.appendChild(parentInstance, child);
|
|
},
|
|
|
|
createInstance(
|
|
type: string,
|
|
props: Props,
|
|
rootContainerInstance: Container,
|
|
hostContext: {},
|
|
internalInstanceHandle: Object,
|
|
): Instance {
|
|
const tag = ReactNativeRTTagHandles.allocateTag();
|
|
precacheFiberNode(internalInstanceHandle, tag);
|
|
updateFiberProps(tag, props);
|
|
RTManager.createNode(tag, type, processProps(tag, props));
|
|
return tag;
|
|
},
|
|
|
|
createTextInstance(
|
|
text: string,
|
|
rootContainerInstance: Container,
|
|
hostContext: {},
|
|
internalInstanceHandle: Object,
|
|
): TextInstance {
|
|
invariant(false, 'Text components are not supported for now.');
|
|
},
|
|
|
|
finalizeInitialChildren(
|
|
parentInstance: Instance,
|
|
type: string,
|
|
props: Props,
|
|
rootContainerInstance: Container,
|
|
): boolean {
|
|
return false;
|
|
},
|
|
|
|
getRootHostContext(): {} {
|
|
return emptyObject;
|
|
},
|
|
|
|
getChildHostContext(): {} {
|
|
return emptyObject;
|
|
},
|
|
|
|
getPublicInstance(instance) {
|
|
return instance;
|
|
},
|
|
|
|
prepareForCommit(): void {
|
|
RTManager.beginUpdates();
|
|
},
|
|
|
|
prepareUpdate(
|
|
instance: Instance,
|
|
type: string,
|
|
oldProps: Props,
|
|
newProps: Props,
|
|
rootContainerInstance: Container,
|
|
hostContext: {},
|
|
): null | Object {
|
|
if (arePropsEqual(oldProps, newProps)) {
|
|
return null;
|
|
}
|
|
return processProps(instance, newProps);
|
|
},
|
|
|
|
resetAfterCommit(): void {
|
|
RTManager.completeUpdates();
|
|
},
|
|
|
|
shouldDeprioritizeSubtree(type: string, props: Props): boolean {
|
|
return false;
|
|
},
|
|
|
|
scheduleDeferredCallback: global.requestIdleCallback,
|
|
cancelDeferredCallback: global.cancelIdleCallback,
|
|
|
|
shouldSetTextContent(type: string, props: Props): boolean {
|
|
// TODO: Figure out when we should allow text content.
|
|
return false;
|
|
},
|
|
|
|
useSyncScheduling: true,
|
|
|
|
now(): number {
|
|
// TODO: Enable expiration by implementing this method.
|
|
return 0;
|
|
},
|
|
|
|
mutation: {
|
|
appendChild(
|
|
parentInstance: Instance,
|
|
child: Instance | TextInstance,
|
|
): void {
|
|
RTManager.appendChild(parentInstance, child);
|
|
},
|
|
|
|
appendChildToContainer(
|
|
parentInstance: Container,
|
|
child: Instance | TextInstance,
|
|
): void {
|
|
RTManager.appendChildToContext(parentInstance, child);
|
|
},
|
|
|
|
commitTextUpdate(
|
|
textInstance: TextInstance,
|
|
oldText: string,
|
|
newText: string,
|
|
): void {
|
|
invariant(false, 'Text components are not yet supported.');
|
|
},
|
|
|
|
commitMount(
|
|
instance: Instance,
|
|
type: string,
|
|
newProps: Props,
|
|
internalInstanceHandle: Object,
|
|
): void {
|
|
// Noop
|
|
},
|
|
|
|
commitUpdate(
|
|
instance: Instance,
|
|
updatePayload: Object,
|
|
type: string,
|
|
oldProps: Props,
|
|
newProps: Props,
|
|
internalInstanceHandle: Object,
|
|
): void {
|
|
updateFiberProps(instance, newProps);
|
|
RTManager.updateNode(instance, updatePayload);
|
|
},
|
|
|
|
insertBefore(
|
|
parentInstance: Instance,
|
|
child: Instance | TextInstance,
|
|
beforeChild: Instance | TextInstance,
|
|
): void {
|
|
RTManager.prependChild(child, beforeChild);
|
|
},
|
|
|
|
insertInContainerBefore(
|
|
parentInstance: Container,
|
|
child: Instance | TextInstance,
|
|
beforeChild: Instance | TextInstance,
|
|
): void {
|
|
RTManager.prependChild(child, beforeChild);
|
|
},
|
|
|
|
removeChild(
|
|
parentInstance: Instance,
|
|
child: Instance | TextInstance,
|
|
): void {
|
|
// TODO: recursively uncache, by traversing fibers, this will currently leak
|
|
RTManager.deleteChild(child);
|
|
},
|
|
|
|
removeChildFromContainer(
|
|
parentInstance: Container,
|
|
child: Instance | TextInstance,
|
|
): void {
|
|
// TODO: recursively uncache, by traversing fibers, this will currently leak
|
|
RTManager.deleteChild(child);
|
|
},
|
|
|
|
resetTextContent(instance: Instance): void {
|
|
// Noop
|
|
},
|
|
},
|
|
});
|
|
|
|
export default NativeRTRenderer;
|