mirror of
https://github.com/facebook/react.git
synced 2026-02-25 05:03:03 +00:00
This covers most everything. The perf suite still needs work for the Element updates. And the server rendering example needs to be done wholesale.
196 lines
5.6 KiB
JavaScript
196 lines
5.6 KiB
JavaScript
var BenchmarkQueue = React.createClass({
|
|
propTypes: {
|
|
debug: React.PropTypes.bool,
|
|
onChange: React.PropTypes.func.isRequired,
|
|
initialQueue: React.PropTypes.array.isRequired,
|
|
maxTime: React.PropTypes.number,
|
|
onCompleteEach: React.PropTypes.func,
|
|
onError: React.PropTypes.func
|
|
},
|
|
|
|
getDefaultProps: function(){
|
|
return {
|
|
maxTime: 5
|
|
};
|
|
},
|
|
|
|
getInitialState: function(){
|
|
return {
|
|
queue: this.props.initialQueue.slice()
|
|
};
|
|
},
|
|
|
|
setItemState: function(state){
|
|
state.test = this.state.queue[0].test;
|
|
state.react = this.state.queue[0].react;
|
|
this.props.onChange(state);
|
|
},
|
|
|
|
handleContextReady: function(window){
|
|
var benchmark = window.Benchmark(window.exports);
|
|
benchmark.options.maxTime = this.props.maxTime; //DEBUG
|
|
|
|
var itemState = {
|
|
testRunnerURL: window.location.href,
|
|
|
|
name: window.exports.name,
|
|
platform: window.Benchmark.platform.description,
|
|
reactVersion: window.React.version,
|
|
|
|
isMinified: (function(){
|
|
var code = window.React.render.toString();
|
|
return code.indexOf(',') - code.indexOf('(') <= 2;
|
|
}())
|
|
};
|
|
|
|
this.setItemState(itemState);
|
|
|
|
var self = this;
|
|
benchmark.on('start error cycle complete', function(){
|
|
var stats = JSON.parse(JSON.stringify(benchmark.stats));
|
|
itemState.stats = stats;
|
|
itemState.isRunning = benchmark.running;
|
|
itemState.error = benchmark.error;
|
|
self.setItemState(itemState);
|
|
});
|
|
if (this.props.onError) {
|
|
benchmark.on('error', this.props.onError);
|
|
}
|
|
benchmark.on('complete', function(){
|
|
var queue = self.state.queue.slice();
|
|
var queueItem = queue.shift();
|
|
if (self.props.onCompleteEach) {
|
|
self.props.onCompleteEach(queueItem);
|
|
}
|
|
self.setState({ queue:queue });
|
|
});
|
|
benchmark.run({async:true});
|
|
},
|
|
|
|
shouldComponentUpdate: function(nextProps, nextState){
|
|
return nextState.queue.length < this.state.queue.length;
|
|
},
|
|
|
|
render: function(){
|
|
if (!(this.state.queue && this.state.queue.length > 0)){
|
|
return React.DOM.div({style:{display:'none'}});
|
|
}
|
|
return BrowserPerfRunnerContext({
|
|
debug: this.props.debug,
|
|
test: this.state.queue[0].test,
|
|
react: this.state.queue[0].react,
|
|
onReady: this.handleContextReady
|
|
});
|
|
}
|
|
});
|
|
|
|
var BrowserPerfRunnerContext = React.createClass({
|
|
|
|
propTypes: {
|
|
debug: React.PropTypes.bool,
|
|
test: function(object, key){
|
|
React.PropTypes.string.isRequired(object, key);
|
|
if (/\.jsx?$/i.test(object[key])) return;
|
|
throw Error('Expected `' + key + '` to be a test file name with extension `.js` or `.jsx`');
|
|
},
|
|
react: function(object, key){
|
|
React.PropTypes.string.isRequired(object, key);
|
|
if (/^(?:builds\/.+|edge|previous|(?:\d+\.){2}\d+)$/.test(object[key])) return;
|
|
throw Error('Expected `' + key + '` prop to be a valid react version string, build string or "edge" or "previous"');
|
|
},
|
|
onReady: React.PropTypes.func.isRequired
|
|
},
|
|
|
|
getInitialState: function(){
|
|
return {
|
|
testRunnerURL:'about:blank'
|
|
};
|
|
},
|
|
|
|
// _handleFrameError: function(error){
|
|
// console.error('BrowserPerfRunnerContext', error);
|
|
// },
|
|
//
|
|
// _handleFrameLoad: function(event){
|
|
// console.log('BrowserPerfRunnerContext', event);
|
|
// },
|
|
//
|
|
_handleMessage: function(event){
|
|
if (location.href.indexOf(event.origin) !== 0)
|
|
return console.debug('BrowserPerfRunnerContext#_handleMessage ignored message from ' + event.origin);
|
|
if (event.source.location.href.indexOf(this.state.testRunnerURL) === -1)
|
|
return console.debug('BrowserPerfRunnerContext#_handleMessage ignored message from ' + event.source.location.href);
|
|
if (event.data !== 'Ready!')
|
|
return console.debug('BrowserPerfRunnerContext#_handleMessage ignored message ' + JSON.stringify(event.data));
|
|
|
|
this.props.onReady(event.source);
|
|
},
|
|
|
|
_getTestRunnerURL: function(props){
|
|
return 'runner.html' +
|
|
'?' +
|
|
'debug=' + (props.debug ? 1 : 0) +
|
|
'&' +
|
|
'react=' + encodeURIComponent(props.react) +
|
|
'&' +
|
|
'test=' + encodeURIComponent(props.test)
|
|
},
|
|
|
|
_renderState: function(props){
|
|
return {
|
|
testRunnerURL: this._getTestRunnerURL(props)
|
|
};
|
|
},
|
|
|
|
componentDidMount: function(){
|
|
var node = this.refs.iframe.getDOMNode();
|
|
// node.onload = this._handleFrameLoad;
|
|
// node.onerror = this._handleFrameError;
|
|
if (window.addEventListener) {
|
|
window.addEventListener('message', this._handleMessage, false);
|
|
} else if (window.attachEvent) {
|
|
window.attachEvent('onmessage', this._handleMessage);
|
|
} else {
|
|
throw Error('cannot attach onmessage listener');
|
|
}
|
|
this.setState(this._renderState(this.props));
|
|
},
|
|
|
|
componentWillUnmount: function(){
|
|
if (window.removeEventListener) {
|
|
window.removeEventListener('message', this._handleMessage);
|
|
} else if (window.detachEvent) {
|
|
window.detachEvent('onmessage', this._handleMessage);
|
|
} else {
|
|
throw Error('cannot detach onmessage listener');
|
|
}
|
|
this.refs.iframe.getDOMNode().src = '';
|
|
},
|
|
|
|
componentWillReceiveProps: function(nextProps){
|
|
this.setState(this._renderState(nextProps));
|
|
},
|
|
|
|
shouldComponentUpdate: function(nextProps, nextState){
|
|
return nextState.testRunnerURL != this.state.testRunnerURL;
|
|
},
|
|
|
|
render: function(){
|
|
return (
|
|
React.DOM.iframe({
|
|
ref: 'iframe',
|
|
name: "BrowserPerfRunnerContextFrame",
|
|
style: this.style,
|
|
src: this.state.testRunnerURL
|
|
})
|
|
);
|
|
},
|
|
|
|
style: {
|
|
position: 'absolute',
|
|
right: '100%',
|
|
bottom: '100%'
|
|
}
|
|
|
|
});
|