Skip to content

Commit

Permalink
Sierpinski Triangle Demo
Browse files Browse the repository at this point in the history
Adds some debug information to ReactDOMFiber
  • Loading branch information
sebmarkbage committed Sep 8, 2016
1 parent d0fd7a2 commit 42fd085
Show file tree
Hide file tree
Showing 2 changed files with 231 additions and 16 deletions.
126 changes: 114 additions & 12 deletions examples/fiber/index.html
Expand Up @@ -19,26 +19,128 @@ <h1>Fiber Example</h1>
</div>
<script src="../../build/react.js"></script>
<script src="../../build/react-dom-fiber.js"></script>
<script>
function ExampleApplication(props) {
var elapsed = Math.round(props.elapsed / 100);
var seconds = elapsed / 10 + (elapsed % 10 ? '' : '.0' );
var message =
'React has been successfully running for ' + seconds + ' seconds.';
<script src="https://cdnjs.cloudflare.com/ajax/libs/babel-core/5.8.24/browser.min.js"></script>
<script type="text/babel">
var dotStyle = {
position: 'absolute',
background: '#61dafb',
font: 'normal 15px sans-serif',
textAlign: 'center',
cursor: 'pointer',
};

var containerStyle = {
position: 'absolute',
transformOrigin: '0 0',
left: '50%',
top: '50%',
width: '10px',
height: '10px',
background: '#eee',
};

var targetSize = 25;

function updateSelection(idx) {
// TODO
}

return React.DOM.p(null, message);
function Dot(props) {
var s = props.size;
var idx = props.idx;
var style = {
...dotStyle,
width: s + 'px',
height: s + 'px',
left: (props.x) + 'px',
top: (props.y) + 'px',
borderRadius: (s / 2) + 'px',
lineHeight: (s) + 'px',
// background: idx === hoveredIdx ? '#ff0' : dotStyle.background
};
return (
<div style={style} onMouseEnter={() => updateSelection(idx)}>
{props.text}
</div>
);
}

// Call React.createFactory instead of directly call ExampleApplication({...}) in React.render
var ExampleApplicationFactory = React.createFactory(ExampleApplication);
function SierpinskiTriangle({ x, y, s, children }) {
if (s <= targetSize) {
return (
<Dot
x={x - (targetSize / 2)}
y={y - (targetSize / 2)}
size={targetSize}
text={children}
/>
);
return r;
}
var newSize = s / 2;
// Artificially long execution time.
var slowDown = true;
if (slowDown) {
s = 0;
while (s < 500000) {
s++;
}
if (s > newSize) {
s = newSize;
}
} else {
s = newSize;
}

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
);
};

function ExampleApplication(props) {
var seconds = (props.elapsed / 1000) % 10;
var scale = 1 + (seconds > 5 ? 10 - seconds : seconds) / 10;
var transform = 'scale(' + (scale / 2.1) + ') translateZ(0.1px)';
var lowPriChildren = true; // change this to false to see the effect

return (
<div style={{ ...containerStyle, transform }}>
<div hidden={lowPriChildren}>
<SierpinskiTriangle x={0} y={0} s={1000}>
{'' + Math.floor(seconds)}
</SierpinskiTriangle>
</div>
</div>
);
}

var start = new Date().getTime();
setInterval(function() {
function update() {
ReactDOMFiber.render(
ExampleApplicationFactory({elapsed: new Date().getTime() - start}),
<ExampleApplication elapsed={new Date().getTime() - start} />,
document.getElementById('container')
);
}, 50);
requestAnimationFrame(update);
}
requestAnimationFrame(update);
</script>
</body>
</html>
121 changes: 117 additions & 4 deletions src/renderers/dom/fiber/ReactDOMFiber.js
Expand Up @@ -18,6 +18,8 @@ var ReactFiberReconciler = require('ReactFiberReconciler');

var warning = require('warning');

type Element = HTMLElement;

type DOMContainerElement = Element & { _reactRootContainer: ?Object };

type Container = Element;
Expand All @@ -41,19 +43,63 @@ function recursivelyAppendChildren(parent : Element, child : HostChildren<Instan
}
}

var COLORS = [
'#1f77b4',
'#ff7f0e',
'#2ca02c',
'#d62728',
'#9467bd',
'#8c564b',
'#e377c2',
'#7f7f7f',
'#bcbd22',
'#17becf',
];

if (!window.requestIdleCallback) {
window.requestIdleCallback = function(callback) {
setTimeout(function() {
var endTime = Date.now() + 16;
callback({
timeRemaining() {
return endTime - Date.now();
},
});

}, 0);
};
}

var VISUALIZE_RECONCILIATION = false;

var DOMRenderer = ReactFiberReconciler({

updateContainer(container : Container, children : HostChildren<Instance>) : void {
if (container.firstChild === children && container.lastChild === children) {
// Rudimentary bail out mechanism.
return;
}
container.innerHTML = '';
recursivelyAppendChildren(container, children);
},

createInstance(type : string, props : Props, children : HostChildren<Instance>) : Instance {
const domElement = document.createElement(type);
recursivelyAppendChildren(domElement, children);
if (typeof props.style === 'object') {
Object.assign(domElement.style, props.style);
}
if (typeof props.onMouseEnter === 'function') {
domElement.addEventListener('mouseenter', props.onMouseEnter);
}
if (typeof props.onMouseLeave === 'function') {
domElement.addEventListener('mouseleave', props.onMouseLeave);
}
if (typeof props.children === 'string') {
domElement.textContent = props.children;
return domElement;
}
domElement.innerHTML = '';
recursivelyAppendChildren(domElement, children);
return domElement;
},

Expand All @@ -63,15 +109,44 @@ var DOMRenderer = ReactFiberReconciler({
newProps : Props,
children : HostChildren<Instance>
) : boolean {
/*
Visualize the reconciliation
*/
if (VISUALIZE_RECONCILIATION && typeof newProps.children === 'string') {
var c = +newProps.children;
if (!isNaN(c)) {
domElement.style.background = COLORS[c];
}
}
return true;
},

beginUpdate(domElement) {
if (VISUALIZE_RECONCILIATION) {
var c = (Math.round(Date.now() / 50) + 2) % COLORS.length;
if (!isNaN(c)) {
domElement.style.border = '3px solid ' + COLORS[c];
}
}
},

commitUpdate(domElement : Instance, oldProps : Props, newProps : Props, children : HostChildren<Instance>) : void {
domElement.innerHTML = '';
recursivelyAppendChildren(domElement, children);
if (typeof newProps.children === 'string') {
domElement.textContent = newProps.children;
return;
}
if (typeof newProps.style === 'object') {
Object.assign(domElement.style, newProps.style);
}
if (children && (domElement.firstChild === children || domElement.firstChild === (children : any).output)) {
// Rudimentary bail out mechanism.
return;
}
if (domElement.firstChild) {
return;
}
domElement.innerHTML = '';
recursivelyAppendChildren(domElement, children);
},
deleteInstance(instance : Instance) : void {
Expand All @@ -95,12 +170,14 @@ function warnAboutUnstableUse() {
warned = true;
}
var rootContainer = null;
var ReactDOM = {
render(element : ReactElement<any>, container : DOMContainerElement) {
warnAboutUnstableUse();
if (!container._reactRootContainer) {
container._reactRootContainer = DOMRenderer.mountContainer(element, container);
container._reactRootContainer = rootContainer = DOMRenderer.mountContainer(element, container);
} else {
DOMRenderer.updateContainer(element, container._reactRootContainer);
}
Expand All @@ -117,6 +194,42 @@ var ReactDOM = {
}
},
// Logs the current state of the tree.
dumpTree() {
if (!rootContainer) {
console.log('Nothing rendered yet.');
return;
}
function logFiber(fiber : any, depth) {
console.log(
' '.repeat(depth) + '- ' + (fiber.type ? fiber.type.name || fiber.type : '[root]'),
'[' + fiber.pendingWorkPriority + (fiber.pendingProps ? '*' : '') + ']'
);
const childInProgress = fiber.childInProgress;
if (childInProgress) {
if (childInProgress === fiber.child) {
console.log(' '.repeat(depth + 1) + 'ERROR: IN PROGRESS == CURRENT');
} else {
console.log(' '.repeat(depth + 1) + 'IN PROGRESS');
logFiber(childInProgress, depth + 1);
if (fiber.child) {
console.log(' '.repeat(depth + 1) + 'CURRENT');
}
}
}
if (fiber.child) {
logFiber(fiber.child, depth + 1);
}
if (fiber.sibling) {
logFiber(fiber.sibling, depth);
}
}

console.log('FIBERS:');
logFiber((rootContainer.stateNode : any).current, 0);
},

};

module.exports = ReactDOM;

0 comments on commit 42fd085

Please sign in to comment.