Files
react/packages/react-test-renderer/src/ReactShallowRenderer.js
T
Dan Abramov 313611572b Reorganize code structure (#11288)
* Move files and tests to more meaningful places

* Fix the build

Now that we import reconciler via react-reconciler, I needed to make a few tweaks.

* Update sizes

* Move @preventMunge directive to FB header

* Revert unintentional change

* Fix Flow coverage

I forgot to @flow-ify those files. This uncovered some issues.

* Prettier, I love you but you're bringing me down
Prettier, I love you but you're bringing me down

Like a rat in a cage
Pulling minimum wage
Prettier, I love you but you're bringing me down

Prettier, you're safer and you're wasting my time
Our records all show you were filthy but fine
But they shuttered your stores
When you opened the doors
To the cops who were bored once they'd run out of crime

Prettier, you're perfect, oh, please don't change a thing
Your mild billionaire mayor's now convinced he's a king
So the boring collect
I mean all disrespect
In the neighborhood bars I'd once dreamt I would drink

Prettier, I love you but you're freaking me out
There's a ton of the twist but we're fresh out of shout
Like a death in the hall
That you hear through your wall
Prettier, I love you but you're freaking me out

Prettier, I love you but you're bringing me down
Prettier, I love you but you're bringing me down
Like a death of the heart
Jesus, where do I start?
But you're still the one pool where I'd happily drown

And oh! Take me off your mailing list
For kids who think it still exists
Yes, for those who think it still exists
Maybe I'm wrong and maybe you're right
Maybe I'm wrong and maybe you're right
Maybe you're right, maybe I'm wrong
And just maybe you're right

And oh! Maybe mother told you true
And there'll always be somebody there for you
And you'll never be alone
But maybe she's wrong and maybe I'm right
And just maybe she's wrong
Maybe she's wrong and maybe I'm right
And if so, here's this song!
2017-10-19 19:50:24 +01:00

273 lines
7.1 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.
*
*/
'use strict';
const checkPropTypes = require('prop-types/checkPropTypes');
const React = require('react');
const emptyObject = require('fbjs/lib/emptyObject');
const invariant = require('fbjs/lib/invariant');
const describeComponentFrame = require('describeComponentFrame');
const getComponentName = require('getComponentName');
class ReactShallowRenderer {
static createRenderer = function() {
return new ReactShallowRenderer();
};
constructor() {
this._context = null;
this._element = null;
this._instance = null;
this._newState = null;
this._rendered = null;
this._rendering = false;
this._forcedUpdate = false;
this._updater = new Updater(this);
}
getMountedInstance() {
return this._instance;
}
getRenderOutput() {
return this._rendered;
}
render(element, context = emptyObject) {
invariant(
React.isValidElement(element),
'ReactShallowRenderer render(): Invalid component element.%s',
typeof element === 'function'
? ' Instead of passing a component class, make sure to instantiate ' +
'it by passing it to React.createElement.'
: '',
);
invariant(
typeof element.type !== 'string',
'ReactShallowRenderer render(): Shallow rendering works only with custom ' +
'components, not primitives (%s). Instead of calling `.render(el)` and ' +
'inspecting the rendered output, look at `el.props` directly instead.',
element.type,
);
if (this._rendering) {
return;
}
this._rendering = true;
this._element = element;
this._context = context;
if (this._instance) {
this._updateClassComponent(element.props, context);
} else {
if (shouldConstruct(element.type)) {
this._instance = new element.type(
element.props,
context,
this._updater,
);
if (element.type.hasOwnProperty('contextTypes')) {
currentlyValidatingElement = element;
checkPropTypes(
element.type.contextTypes,
context,
'context',
getName(element.type, this._instance),
getStackAddendum,
);
currentlyValidatingElement = null;
}
this._mountClassComponent(element.props, context);
} else {
this._rendered = element.type(element.props, context);
}
}
this._rendering = false;
return this.getRenderOutput();
}
unmount() {
if (this._instance) {
if (typeof this._instance.componentWillUnmount === 'function') {
this._instance.componentWillUnmount();
}
}
this._context = null;
this._element = null;
this._newState = null;
this._rendered = null;
this._instance = null;
}
_mountClassComponent(props, context) {
this._instance.context = context;
this._instance.props = props;
this._instance.state = this._instance.state || emptyObject;
this._instance.updater = this._updater;
if (typeof this._instance.componentWillMount === 'function') {
const beforeState = this._newState;
this._instance.componentWillMount();
// setState may have been called during cWM
if (beforeState !== this._newState) {
this._instance.state = this._newState || emptyObject;
}
}
this._rendered = this._instance.render();
// Intentionally do not call componentDidMount()
// because DOM refs are not available.
}
_updateClassComponent(props, context) {
const oldProps = this._instance.props;
if (
oldProps !== props &&
typeof this._instance.componentWillReceiveProps === 'function'
) {
this._instance.componentWillReceiveProps(props, context);
}
// Read state after cWRP in case it calls setState
// Fallback to previous instance state to support rendering React.cloneElement()
const state = this._newState || this._instance.state || emptyObject;
if (typeof this._instance.shouldComponentUpdate === 'function') {
if (
this._forcedUpdate ||
this._instance.shouldComponentUpdate(props, state, context) === false
) {
this._instance.context = context;
this._instance.props = props;
this._instance.state = state;
this._forcedUpdate = false;
return;
}
}
if (typeof this._instance.componentWillUpdate === 'function') {
this._instance.componentWillUpdate(props, state, context);
}
this._instance.context = context;
this._instance.props = props;
this._instance.state = state;
this._rendered = this._instance.render();
// Intentionally do not call componentDidUpdate()
// because DOM refs are not available.
}
}
class Updater {
constructor(renderer) {
this._renderer = renderer;
}
isMounted(publicInstance) {
return !!this._renderer._element;
}
enqueueForceUpdate(publicInstance, callback, callerName) {
this._renderer._forcedUpdate = true;
this._renderer.render(this._renderer._element, this._renderer._context);
if (typeof callback === 'function') {
callback.call(publicInstance);
}
}
enqueueReplaceState(publicInstance, completeState, callback, callerName) {
this._renderer._newState = completeState;
this._renderer.render(this._renderer._element, this._renderer._context);
if (typeof callback === 'function') {
callback.call(publicInstance);
}
}
enqueueSetState(publicInstance, partialState, callback, callerName) {
const currentState = this._renderer._newState || publicInstance.state;
if (typeof partialState === 'function') {
partialState = partialState(currentState, publicInstance.props);
}
this._renderer._newState = {
...currentState,
...partialState,
};
this._renderer.render(this._renderer._element, this._renderer._context);
if (typeof callback === 'function') {
callback.call(publicInstance);
}
}
}
var currentlyValidatingElement = null;
function getDisplayName(element) {
if (element == null) {
return '#empty';
} else if (typeof element === 'string' || typeof element === 'number') {
return '#text';
} else if (typeof element.type === 'string') {
return element.type;
} else {
return element.type.displayName || element.type.name || 'Unknown';
}
}
function getStackAddendum() {
var stack = '';
if (currentlyValidatingElement) {
var name = getDisplayName(currentlyValidatingElement);
var owner = currentlyValidatingElement._owner;
stack += describeComponentFrame(
name,
currentlyValidatingElement._source,
owner && getComponentName(owner),
);
}
return stack;
}
function getName(type, instance) {
var constructor = instance && instance.constructor;
return (
type.displayName ||
(constructor && constructor.displayName) ||
type.name ||
(constructor && constructor.name) ||
null
);
}
function shouldConstruct(Component) {
return !!(Component.prototype && Component.prototype.isReactComponent);
}
module.exports = ReactShallowRenderer;