Run 'prettier' on the v15.6 branch (#9487)

* Run 'prettier' on the v15.6 branch

This is an easy fix and I'd like this branch to be as similar to master
(v16.0) as possible.

* `npm install --save-dev prettier && yarn prettier`

Checking in the updated `package.json` and `yarn.lock` for the 15.6
branch.

Oddly, running `yarn prettier` updated more files. I thought the
previous commit had covered all `prettier` syntax updates. Will commit
the new changes in a separate commit.

* Ran prettier

More syntax updates to get `prettier` checks passing on the `15.6-dev`
branch, and eventually, on 15-stable.

* Tweak eslint ignore comments to get linter passing

Something with running `prettier` moves or changes these comments in a
way that they were no longer being applied. We tweaked them so that both
'prettier' and 'eslint' pass.
This commit is contained in:
Flarnie Marchan
2017-04-22 11:36:25 -07:00
committed by GitHub
parent 1926f9ab06
commit ad1d3526f5
287 changed files with 9348 additions and 7893 deletions
+1
View File
@@ -71,6 +71,7 @@
"merge-stream": "^1.0.0",
"object-assign": "^4.1.1",
"platform": "^1.1.0",
"prettier": "^1.2.2",
"prop-types": "15.5.7",
"run-sequence": "^1.1.4",
"through2": "^2.0.0",
+5 -5
View File
@@ -41,7 +41,7 @@ var ReactFragment = {
warning(
false,
'React.addons.createFragment only accepts a single object. Got: %s',
object
object,
);
return object;
}
@@ -49,7 +49,7 @@ var ReactFragment = {
warning(
false,
'React.addons.createFragment does not accept a ReactElement ' +
'without a wrapper object.'
'without a wrapper object.',
);
return object;
}
@@ -57,7 +57,7 @@ var ReactFragment = {
invariant(
object.nodeType !== 1,
'React.addons.createFragment(...): Encountered an invalid child; DOM ' +
'elements are not valid children of React components.'
'elements are not valid children of React components.',
);
var result = [];
@@ -68,7 +68,7 @@ var ReactFragment = {
warning(
false,
'React.addons.createFragment(...): Child objects should have ' +
'non-numeric keys so ordering is preserved.'
'non-numeric keys so ordering is preserved.',
);
warnedAboutNumeric = true;
}
@@ -77,7 +77,7 @@ var ReactFragment = {
object[key],
result,
key,
emptyFunction.thatReturnsArgument
emptyFunction.thatReturnsArgument,
);
}
+1 -2
View File
@@ -14,8 +14,7 @@
var LinkedStateMixin = require('LinkedStateMixin');
var React = require('React');
var ReactAddonsDOMDependencies = require('ReactAddonsDOMDependencies');
var ReactComponentWithPureRenderMixin =
require('ReactComponentWithPureRenderMixin');
var ReactComponentWithPureRenderMixin = require('ReactComponentWithPureRenderMixin');
var ReactCSSTransitionGroup = require('ReactCSSTransitionGroup');
var ReactFragment = require('ReactFragment');
var ReactTransitionGroup = require('ReactTransitionGroup');
+13 -15
View File
@@ -16,7 +16,6 @@ var ReactDOM;
var ReactFragment;
describe('ReactFragment', () => {
beforeEach(() => {
React = require('React');
ReactDOM = require('ReactDOM');
@@ -33,9 +32,9 @@ describe('ReactFragment', () => {
var container = document.createElement('div');
expect(() => ReactDOM.render(element, container)).toThrowError(
'Objects are not valid as a React child (found: object with keys ' +
'{x, y, z}). If you meant to render a collection of children, use an ' +
'array instead or wrap the object using createFragment(object) from ' +
'the React add-ons.'
'{x, y, z}). If you meant to render a collection of children, use an ' +
'array instead or wrap the object using createFragment(object) from ' +
'the React add-ons.',
);
});
@@ -53,9 +52,9 @@ describe('ReactFragment', () => {
var container = document.createElement('div');
expect(() => ReactDOM.render(<Foo />, container)).toThrowError(
'Objects are not valid as a React child (found: object with keys ' +
'{a, b, c}). If you meant to render a collection of children, use an ' +
'array instead or wrap the object using createFragment(object) from ' +
'the React add-ons. Check the render method of `Foo`.'
'{a, b, c}). If you meant to render a collection of children, use an ' +
'array instead or wrap the object using createFragment(object) from ' +
'the React add-ons. Check the render method of `Foo`.',
);
});
@@ -64,9 +63,9 @@ describe('ReactFragment', () => {
var container = document.createElement('div');
expect(() => ReactDOM.render(<div>{oldEl}</div>, container)).toThrowError(
'Objects are not valid as a React child (found: object with keys ' +
'{_isReactElement, type, props}). It looks like you\'re using an ' +
'element created by a different version of React. Make sure to use ' +
'only one copy of React.'
"{_isReactElement, type, props}). It looks like you're using an " +
'element created by a different version of React. Make sure to use ' +
'only one copy of React.',
);
});
@@ -77,7 +76,7 @@ describe('ReactFragment', () => {
expect(console.error.calls.count()).toBe(1);
expect(console.error.calls.argsFor(0)[0]).toContain(
'Child objects should have non-numeric keys so ordering is preserved.'
'Child objects should have non-numeric keys so ordering is preserved.',
);
});
@@ -86,7 +85,7 @@ describe('ReactFragment', () => {
ReactFragment.create(null);
expect(console.error.calls.count()).toBe(1);
expect(console.error.calls.argsFor(0)[0]).toContain(
'React.addons.createFragment only accepts a single object.'
'React.addons.createFragment only accepts a single object.',
);
});
@@ -95,7 +94,7 @@ describe('ReactFragment', () => {
ReactFragment.create([]);
expect(console.error.calls.count()).toBe(1);
expect(console.error.calls.argsFor(0)[0]).toContain(
'React.addons.createFragment only accepts a single object.'
'React.addons.createFragment only accepts a single object.',
);
});
@@ -105,8 +104,7 @@ describe('ReactFragment', () => {
expect(console.error.calls.count()).toBe(1);
expect(console.error.calls.argsFor(0)[0]).toContain(
'React.addons.createFragment does not accept a ReactElement without a ' +
'wrapper object.'
'wrapper object.',
);
});
});
@@ -17,7 +17,6 @@ var ReactTestUtils = require('ReactTestUtils');
var renderSubtreeIntoContainer = require('renderSubtreeIntoContainer');
describe('renderSubtreeIntoContainer', () => {
it('should pass context when rendering subtree elsewhere', () => {
var portal = document.createElement('div');
@@ -47,9 +46,11 @@ describe('renderSubtreeIntoContainer', () => {
}
componentDidMount() {
expect(function() {
renderSubtreeIntoContainer(this, <Component />, portal);
}.bind(this)).not.toThrow();
expect(
function() {
renderSubtreeIntoContainer(this, <Component />, portal);
}.bind(this),
).not.toThrow();
}
}
@@ -195,5 +196,4 @@ describe('renderSubtreeIntoContainer', () => {
ReactDOM.render(<Parent bar="changed" />, container);
expect(portal.firstChild.innerHTML).toBe('changed-changed');
});
});
+39 -35
View File
@@ -14,7 +14,6 @@
var update = require('update');
describe('update', () => {
describe('$push', () => {
it('pushes', () => {
expect(update([1], {$push: [7]})).toEqual([1, 7]);
@@ -27,12 +26,12 @@ describe('update', () => {
it('only pushes an array', () => {
expect(update.bind(null, [], {$push: 7})).toThrowError(
'update(): expected spec of $push to be an array; got 7. Did you ' +
'forget to wrap your parameter in an array?'
'forget to wrap your parameter in an array?',
);
});
it('only pushes unto an array', () => {
expect(update.bind(null, 1, {$push: 7})).toThrowError(
'update(): expected target of $push to be an array; got 1.'
'update(): expected target of $push to be an array; got 1.',
);
});
});
@@ -49,12 +48,12 @@ describe('update', () => {
it('only unshifts an array', () => {
expect(update.bind(null, [], {$unshift: 7})).toThrowError(
'update(): expected spec of $unshift to be an array; got 7. Did you ' +
'forget to wrap your parameter in an array?'
'forget to wrap your parameter in an array?',
);
});
it('only unshifts unto an array', () => {
expect(update.bind(null, 1, {$unshift: 7})).toThrowError(
'update(): expected target of $unshift to be an array; got 1.'
'update(): expected target of $unshift to be an array; got 1.',
);
});
});
@@ -71,16 +70,16 @@ describe('update', () => {
it('only splices an array of arrays', () => {
expect(update.bind(null, [], {$splice: 1})).toThrowError(
'update(): expected spec of $splice to be an array of arrays; got 1. ' +
'Did you forget to wrap your parameters in an array?'
'Did you forget to wrap your parameters in an array?',
);
expect(update.bind(null, [], {$splice: [1]})).toThrowError(
'update(): expected spec of $splice to be an array of arrays; got 1. ' +
'Did you forget to wrap your parameters in an array?'
'Did you forget to wrap your parameters in an array?',
);
});
it('only splices unto an array', () => {
expect(update.bind(null, 1, {$splice: 7})).toThrowError(
'Expected $splice target to be an array; got 1'
'Expected $splice target to be an array; got 1',
);
});
});
@@ -96,12 +95,12 @@ describe('update', () => {
});
it('only merges with an object', () => {
expect(update.bind(null, {}, {$merge: 7})).toThrowError(
'update(): $merge expects a spec of type \'object\'; got 7'
"update(): $merge expects a spec of type 'object'; got 7",
);
});
it('only merges with an object', () => {
expect(update.bind(null, 7, {$merge: {a: 'b'}})).toThrowError(
'update(): $merge expects a target of type \'object\'; got 7'
"update(): $merge expects a target of type 'object'; got 7",
);
});
});
@@ -131,32 +130,37 @@ describe('update', () => {
});
it('only applies a function', () => {
expect(update.bind(null, 2, {$apply: 123})).toThrowError(
'update(): expected spec of $apply to be a function; got 123.'
'update(): expected spec of $apply to be a function; got 123.',
);
});
});
it('should support deep updates', () => {
expect(update({
a: 'b',
c: {
d: 'e',
f: [1],
g: [2],
h: [3],
i: {j: 'k'},
l: 4,
},
}, {
c: {
d: {$set: 'm'},
f: {$push: [5]},
g: {$unshift: [6]},
h: {$splice: [[0, 1, 7]]},
i: {$merge: {n: 'o'}},
l: {$apply: (x) => x * 2},
},
})).toEqual({
expect(
update(
{
a: 'b',
c: {
d: 'e',
f: [1],
g: [2],
h: [3],
i: {j: 'k'},
l: 4,
},
},
{
c: {
d: {$set: 'm'},
f: {$push: [5]},
g: {$unshift: [6]},
h: {$splice: [[0, 1, 7]]},
i: {$merge: {n: 'o'}},
l: {$apply: x => x * 2},
},
},
),
).toEqual({
a: 'b',
c: {
d: 'm',
@@ -172,14 +176,14 @@ describe('update', () => {
it('should require a command', () => {
expect(update.bind(null, {a: 'b'}, {a: 'c'})).toThrowError(
'update(): You provided a key path to update() that did not contain ' +
'one of $push, $unshift, $splice, $set, $merge, $apply. Did you ' +
'forget to include {$set: ...}?'
'one of $push, $unshift, $splice, $set, $merge, $apply. Did you ' +
'forget to include {$set: ...}?',
);
});
it('should perform safe hasOwnProperty check', () => {
expect(update({}, {'hasOwnProperty': {$set: 'a'}})).toEqual({
'hasOwnProperty': 'a',
expect(update({}, {hasOwnProperty: {$set: 'a'}})).toEqual({
hasOwnProperty: 'a',
});
});
});
+1 -1
View File
@@ -30,7 +30,7 @@ var LinkedStateMixin = {
linkState: function(key) {
return new ReactLink(
this.state[key],
ReactStateSetters.createStateKeySetter(this, key)
ReactStateSetters.createStateKeySetter(this, key),
);
},
};
+3 -3
View File
@@ -58,9 +58,9 @@ function ReactLink(value, requestChange) {
*/
function createLinkTypeChecker(linkType) {
var shapes = {
value: linkType === undefined ?
React.PropTypes.any.isRequired :
linkType.isRequired,
value: linkType === undefined
? React.PropTypes.any.isRequired
: linkType.isRequired,
requestChange: React.PropTypes.func.isRequired,
};
return React.PropTypes.shape(shapes);
@@ -28,16 +28,19 @@ function createTransitionTimeoutPropValidator(transitionType) {
// If no timeout duration is provided
if (props[timeoutPropName] == null) {
return new Error(
timeoutPropName + ' wasn\'t supplied to ReactCSSTransitionGroup: ' +
'this can cause unreliable animations and won\'t be supported in ' +
'a future version of React. See ' +
'https://fb.me/react-animation-transition-group-timeout for more ' +
'information.'
timeoutPropName +
" wasn't supplied to ReactCSSTransitionGroup: " +
"this can cause unreliable animations and won't be supported in " +
'a future version of React. See ' +
'https://fb.me/react-animation-transition-group-timeout for more ' +
'information.',
);
// If the duration isn't a number
// If the duration isn't a number
} else if (typeof props[timeoutPropName] !== 'number') {
return new Error(timeoutPropName + ' must be a number (in milliseconds)');
return new Error(
timeoutPropName + ' must be a number (in milliseconds)',
);
}
}
};
@@ -68,7 +71,7 @@ class ReactCSSTransitionGroup extends React.Component {
transitionLeave: true,
};
_wrapChild = (child) => {
_wrapChild = child => {
// We need to provide this childFactory so that
// ReactCSSTransitionGroupChild can receive updates to name, enter, and
// leave while it is leaving.
@@ -83,14 +86,14 @@ class ReactCSSTransitionGroup extends React.Component {
enterTimeout: this.props.transitionEnterTimeout,
leaveTimeout: this.props.transitionLeaveTimeout,
},
child
child,
);
};
render() {
return React.createElement(
ReactTransitionGroup,
Object.assign({}, this.props, {childFactory: this._wrapChild})
Object.assign({}, this.props, {childFactory: this._wrapChild}),
);
}
}
@@ -17,7 +17,6 @@ var ReactAddonsDOMDependencies = require('ReactAddonsDOMDependencies');
var propTypesFactory = require('prop-types/factory');
var PropTypes = propTypesFactory(React.isValidElement);
var CSSCore = require('CSSCore');
var ReactTransitionEvents = require('ReactTransitionEvents');
@@ -67,8 +66,10 @@ class ReactCSSTransitionGroupChild extends React.Component {
return;
}
var className = this.props.name[animationType] || this.props.name + '-' + animationType;
var activeClassName = this.props.name[animationType + 'Active'] || className + '-active';
var className =
this.props.name[animationType] || this.props.name + '-' + animationType;
var activeClassName =
this.props.name[animationType + 'Active'] || className + '-active';
var timeout = null;
var endListener = function(e) {
@@ -149,29 +150,29 @@ class ReactCSSTransitionGroupChild extends React.Component {
this.classNameAndNodeQueue.length = 0;
}
componentWillAppear = (done) => {
componentWillAppear = done => {
if (this.props.appear) {
this.transition('appear', done, this.props.appearTimeout);
} else {
done();
}
}
};
componentWillEnter = (done) => {
componentWillEnter = done => {
if (this.props.enter) {
this.transition('enter', done, this.props.enterTimeout);
} else {
done();
}
}
};
componentWillLeave = (done) => {
componentWillLeave = done => {
if (this.props.leave) {
this.transition('leave', done, this.props.leaveTimeout);
} else {
done();
}
}
};
render() {
return onlyChild(this.props.children);
@@ -86,7 +86,7 @@ var ReactTransitionChildMapping = {
for (i = 0; i < nextKeysPending[nextKey].length; i++) {
var pendingNextKey = nextKeysPending[nextKey][i];
childMapping[nextKeysPending[nextKey][i]] = getValueForKey(
pendingNextKey
pendingNextKey,
);
}
}
+30 -30
View File
@@ -59,14 +59,14 @@ class ReactTransitionGroup extends React.Component {
componentWillReceiveProps(nextProps) {
var nextChildMapping = ReactTransitionChildMapping.getChildMapping(
nextProps.children
nextProps.children,
);
var prevChildMapping = this.state.children;
this.setState({
children: ReactTransitionChildMapping.mergeChildMappings(
prevChildMapping,
nextChildMapping
nextChildMapping,
),
});
@@ -74,16 +74,22 @@ class ReactTransitionGroup extends React.Component {
for (key in nextChildMapping) {
var hasPrev = prevChildMapping && prevChildMapping.hasOwnProperty(key);
if (nextChildMapping[key] && !hasPrev &&
!this.currentlyTransitioningKeys[key]) {
if (
nextChildMapping[key] &&
!hasPrev &&
!this.currentlyTransitioningKeys[key]
) {
this.keysToEnter.push(key);
}
}
for (key in prevChildMapping) {
var hasNext = nextChildMapping && nextChildMapping.hasOwnProperty(key);
if (prevChildMapping[key] && !hasNext &&
!this.currentlyTransitioningKeys[key]) {
if (
prevChildMapping[key] &&
!hasNext &&
!this.currentlyTransitioningKeys[key]
) {
this.keysToLeave.push(key);
}
}
@@ -101,21 +107,19 @@ class ReactTransitionGroup extends React.Component {
keysToLeave.forEach(this.performLeave);
}
performAppear = (key) => {
performAppear = key => {
this.currentlyTransitioningKeys[key] = true;
var component = this.refs[key];
if (component.componentWillAppear) {
component.componentWillAppear(
this._handleDoneAppearing.bind(this, key)
);
component.componentWillAppear(this._handleDoneAppearing.bind(this, key));
} else {
this._handleDoneAppearing(key);
}
};
_handleDoneAppearing = (key) => {
_handleDoneAppearing = key => {
var component = this.refs[key];
if (component.componentDidAppear) {
component.componentDidAppear();
@@ -124,7 +128,7 @@ class ReactTransitionGroup extends React.Component {
delete this.currentlyTransitioningKeys[key];
var currentChildMapping = ReactTransitionChildMapping.getChildMapping(
this.props.children
this.props.children,
);
if (!currentChildMapping || !currentChildMapping.hasOwnProperty(key)) {
@@ -133,21 +137,19 @@ class ReactTransitionGroup extends React.Component {
}
};
performEnter = (key) => {
performEnter = key => {
this.currentlyTransitioningKeys[key] = true;
var component = this.refs[key];
if (component.componentWillEnter) {
component.componentWillEnter(
this._handleDoneEntering.bind(this, key)
);
component.componentWillEnter(this._handleDoneEntering.bind(this, key));
} else {
this._handleDoneEntering(key);
}
};
_handleDoneEntering = (key) => {
_handleDoneEntering = key => {
var component = this.refs[key];
if (component.componentDidEnter) {
component.componentDidEnter();
@@ -156,7 +158,7 @@ class ReactTransitionGroup extends React.Component {
delete this.currentlyTransitioningKeys[key];
var currentChildMapping = ReactTransitionChildMapping.getChildMapping(
this.props.children
this.props.children,
);
if (!currentChildMapping || !currentChildMapping.hasOwnProperty(key)) {
@@ -165,7 +167,7 @@ class ReactTransitionGroup extends React.Component {
}
};
performLeave = (key) => {
performLeave = key => {
this.currentlyTransitioningKeys[key] = true;
var component = this.refs[key];
@@ -179,7 +181,7 @@ class ReactTransitionGroup extends React.Component {
}
};
_handleDoneLeaving = (key) => {
_handleDoneLeaving = key => {
var component = this.refs[key];
if (component.componentDidLeave) {
@@ -189,7 +191,7 @@ class ReactTransitionGroup extends React.Component {
delete this.currentlyTransitioningKeys[key];
var currentChildMapping = ReactTransitionChildMapping.getChildMapping(
this.props.children
this.props.children,
);
if (currentChildMapping && currentChildMapping.hasOwnProperty(key)) {
@@ -216,10 +218,12 @@ class ReactTransitionGroup extends React.Component {
// already been removed. In case you need this behavior you can provide
// a childFactory function to wrap every child, even the ones that are
// leaving.
childrenToRender.push(React.cloneElement(
this.props.childFactory(child),
{ref: key, key: key}
));
childrenToRender.push(
React.cloneElement(this.props.childFactory(child), {
ref: key,
key: key,
}),
);
}
}
@@ -235,11 +239,7 @@ class ReactTransitionGroup extends React.Component {
delete props.transitionAppearTimeout;
delete props.component;
return React.createElement(
this.props.component,
props,
childrenToRender
);
return React.createElement(this.props.component, props, childrenToRender);
}
}
@@ -27,7 +27,7 @@ describe('ReactTransitionChildMapping', () => {
var two = <div key="two" />;
var component = <div>{one}{two}</div>;
expect(
ReactTransitionChildMapping.getChildMapping(component.props.children)
ReactTransitionChildMapping.getChildMapping(component.props.children),
).toEqual({
'.$one': one,
'.$two': two,
+17 -17
View File
@@ -9,7 +9,7 @@
* @providesModule update
*/
/* global hasOwnProperty:true */
/* global hasOwnProperty:true */
'use strict';
@@ -53,15 +53,15 @@ function invariantArrayCase(value, spec, command) {
Array.isArray(value),
'update(): expected target of %s to be an array; got %s.',
command,
value
value,
);
var specValue = spec[command];
invariant(
Array.isArray(specValue),
'update(): expected spec of %s to be an array; got %s. ' +
'Did you forget to wrap your parameter in an array?',
'Did you forget to wrap your parameter in an array?',
command,
specValue
specValue,
);
}
@@ -73,16 +73,16 @@ function update(value, spec) {
invariant(
typeof spec === 'object',
'update(): You provided a key path to update() that did not contain one ' +
'of %s. Did you forget to include {%s: ...}?',
'of %s. Did you forget to include {%s: ...}?',
ALL_COMMANDS_LIST.join(', '),
COMMAND_SET
COMMAND_SET,
);
if (hasOwnProperty.call(spec, COMMAND_SET)) {
invariant(
Object.keys(spec).length === 1,
'Cannot have more than one key in an object with %s',
COMMAND_SET
COMMAND_SET,
);
return spec[COMMAND_SET];
@@ -94,15 +94,15 @@ function update(value, spec) {
var mergeObj = spec[COMMAND_MERGE];
invariant(
mergeObj && typeof mergeObj === 'object',
'update(): %s expects a spec of type \'object\'; got %s',
"update(): %s expects a spec of type 'object'; got %s",
COMMAND_MERGE,
mergeObj
mergeObj,
);
invariant(
nextValue && typeof nextValue === 'object',
'update(): %s expects a target of type \'object\'; got %s',
"update(): %s expects a target of type 'object'; got %s",
COMMAND_MERGE,
nextValue
nextValue,
);
Object.assign(nextValue, spec[COMMAND_MERGE]);
}
@@ -126,22 +126,22 @@ function update(value, spec) {
Array.isArray(value),
'Expected %s target to be an array; got %s',
COMMAND_SPLICE,
value
value,
);
invariant(
Array.isArray(spec[COMMAND_SPLICE]),
'update(): expected spec of %s to be an array of arrays; got %s. ' +
'Did you forget to wrap your parameters in an array?',
'Did you forget to wrap your parameters in an array?',
COMMAND_SPLICE,
spec[COMMAND_SPLICE]
spec[COMMAND_SPLICE],
);
spec[COMMAND_SPLICE].forEach(function(args) {
invariant(
Array.isArray(args),
'update(): expected spec of %s to be an array of arrays; got %s. ' +
'Did you forget to wrap your parameters in an array?',
'Did you forget to wrap your parameters in an array?',
COMMAND_SPLICE,
spec[COMMAND_SPLICE]
spec[COMMAND_SPLICE],
);
nextValue.splice.apply(nextValue, args);
});
@@ -152,7 +152,7 @@ function update(value, spec) {
typeof spec[COMMAND_APPLY] === 'function',
'update(): expected spec of %s to be a function; got %s.',
COMMAND_APPLY,
spec[COMMAND_APPLY]
spec[COMMAND_APPLY],
);
nextValue = spec[COMMAND_APPLY](nextValue);
}
+5 -7
View File
@@ -48,9 +48,9 @@ if (__DEV__) {
warning(
warnedForSpread,
'React.__spread is deprecated and should not be used. Use ' +
'Object.assign directly or another helper function with similar ' +
'semantics. You may be seeing this warning due to your compiler. ' +
'See https://fb.me/react-spread-deprecation for more details.'
'Object.assign directly or another helper function with similar ' +
'semantics. You may be seeing this warning due to your compiler. ' +
'See https://fb.me/react-spread-deprecation for more details.',
);
warnedForSpread = true;
return Object.assign.apply(null, arguments);
@@ -60,16 +60,14 @@ if (__DEV__) {
warning(
warnedForCreateMixin,
'React.createMixin is deprecated and should not be used. You ' +
'can use this mixin directly instead.'
'can use this mixin directly instead.',
);
warnedForCreateMixin = true;
return mixin;
};
}
var React = {
// Modern
Children: {
@@ -112,7 +110,7 @@ if (__DEV__) {
warning(
didWarnPropTypesDeprecated,
'Accessing PropTypes via the main React package is deprecated. Use ' +
'the prop-types package from npm instead.'
'the prop-types package from npm instead.',
);
didWarnPropTypesDeprecated = true;
return ReactPropTypes;
+2 -4
View File
@@ -12,7 +12,6 @@
'use strict';
describe('React', () => {
var React;
beforeEach(() => {
@@ -25,7 +24,7 @@ describe('React', () => {
React.__spread({});
expect(console.error.calls.count()).toBe(1);
expect(console.error.calls.argsFor(0)[0]).toContain(
'React.__spread is deprecated and should not be used'
'React.__spread is deprecated and should not be used',
);
});
@@ -35,8 +34,7 @@ describe('React', () => {
React.createMixin();
expect(console.error.calls.count()).toBe(1);
expect(console.error.calls.argsFor(0)[0]).toContain(
'React.createMixin is deprecated and should not be used'
'React.createMixin is deprecated and should not be used',
);
});
});
+11 -18
View File
@@ -20,13 +20,11 @@ var traverseAllChildren = require('traverseAllChildren');
var twoArgumentPooler = PooledClass.twoArgumentPooler;
var fourArgumentPooler = PooledClass.fourArgumentPooler;
var userProvidedKeyEscapeRegex = /\/+/g;
function escapeUserProvidedKey(text) {
return ('' + text).replace(userProvidedKeyEscapeRegex, '$&/');
}
/**
* PooledClass representing the bookkeeping associated with performing a child
* traversal. Allows avoiding binding callbacks.
@@ -68,13 +66,14 @@ function forEachChildren(children, forEachFunc, forEachContext) {
if (children == null) {
return children;
}
var traverseContext =
ForEachBookKeeping.getPooled(forEachFunc, forEachContext);
var traverseContext = ForEachBookKeeping.getPooled(
forEachFunc,
forEachContext,
);
traverseAllChildren(children, forEachSingleChild, traverseContext);
ForEachBookKeeping.release(traverseContext);
}
/**
* PooledClass representing the bookkeeping associated with performing a child
* mapping. Allows avoiding binding callbacks.
@@ -109,7 +108,7 @@ function mapSingleChildIntoContext(bookKeeping, child, childKey) {
mappedChild,
result,
childKey,
emptyFunction.thatReturnsArgument
emptyFunction.thatReturnsArgument,
);
} else if (mappedChild != null) {
if (ReactElement.isValidElement(mappedChild)) {
@@ -118,12 +117,10 @@ function mapSingleChildIntoContext(bookKeeping, child, childKey) {
// Keep both the (mapped) and old keys if they differ, just as
// traverseAllChildren used to do for objects as children
keyPrefix +
(
(mappedChild.key && (!child || (child.key !== mappedChild.key))) ?
escapeUserProvidedKey(mappedChild.key) + '/' :
''
) +
childKey
(mappedChild.key && (!child || child.key !== mappedChild.key)
? escapeUserProvidedKey(mappedChild.key) + '/'
: '') +
childKey,
);
}
result.push(mappedChild);
@@ -139,7 +136,7 @@ function mapIntoWithKeyPrefixInternal(children, array, prefix, func, context) {
array,
escapedPrefix,
func,
context
context,
);
traverseAllChildren(children, mapSingleChildIntoContext, traverseContext);
MapBookKeeping.release(traverseContext);
@@ -167,8 +164,6 @@ function mapChildren(children, func, context) {
return result;
}
function forEachSingleChildDummy(traverseContext, child, name) {
return null;
}
@@ -186,7 +181,6 @@ function countChildren(children, context) {
return traverseAllChildren(children, forEachSingleChildDummy, null);
}
/**
* Flatten a children object (typically specified as `props.children`) and
* return an array with appropriately re-keyed children.
@@ -199,12 +193,11 @@ function toArray(children) {
children,
result,
null,
emptyFunction.thatReturnsArgument
emptyFunction.thatReturnsArgument,
);
return result;
}
var ReactChildren = {
forEach: forEachChildren,
map: mapChildren,
@@ -69,7 +69,6 @@ describe('ReactChildren', () => {
var mappedChildren = ReactChildren.map(instance.props.children, callback);
expect(callback).toHaveBeenCalledWith(simpleKid, 0);
expect(mappedChildren[0]).toEqual(<span key=".$simple" />);
});
it('should pass key to returned component', () => {
@@ -103,8 +102,11 @@ describe('ReactChildren', () => {
ReactChildren.forEach(instance.props.children, callback, scopeTester);
expect(lastContext).toBe(scopeTester);
var mappedChildren =
ReactChildren.map(instance.props.children, callback, scopeTester);
var mappedChildren = ReactChildren.map(
instance.props.children,
callback,
scopeTester,
);
expect(ReactChildren.count(mappedChildren)).toBe(1);
expect(mappedChildren[0]).toBe(scopeTester);
@@ -118,9 +120,9 @@ describe('ReactChildren', () => {
var four = <div key="keyFour" />;
var mapped = [
<div key="giraffe" />, // Key should be joined to obj key
null, // Key should be added even if we don't supply it!
<div />, // Key should be added even if not supplied!
<div key="giraffe" />, // Key should be joined to obj key
null, // Key should be added even if we don't supply it!
<div />, // Key should be added even if not supplied!
<span />, // Map from null to something.
<div key="keyFour" />,
];
@@ -146,8 +148,7 @@ describe('ReactChildren', () => {
expect(callback).toHaveBeenCalledWith(four, 4);
callback.calls.reset();
var mappedChildren =
ReactChildren.map(instance.props.children, callback);
var mappedChildren = ReactChildren.map(instance.props.children, callback);
expect(callback.calls.count()).toBe(5);
expect(ReactChildren.count(mappedChildren)).toBe(4);
// Keys default to indices.
@@ -156,9 +157,7 @@ describe('ReactChildren', () => {
mappedChildren[1].key,
mappedChildren[2].key,
mappedChildren[3].key,
]).toEqual(
['giraffe/.$keyZero', '.$keyTwo', '.3', '.$keyFour']
);
]).toEqual(['giraffe/.$keyZero', '.$keyTwo', '.3', '.$keyFour']);
expect(callback).toHaveBeenCalledWith(zero, 0);
expect(callback).toHaveBeenCalledWith(one, 1);
@@ -185,15 +184,15 @@ describe('ReactChildren', () => {
// 1. If grouped in an Object, the object key combined with `key` prop
// 2. If grouped in an Array, the `key` prop, falling back to array index
var zeroMapped = <div key="giraffe" />; // Key should be overridden
var twoMapped = <div />; // Key should be added even if not supplied!
var zeroMapped = <div key="giraffe" />; // Key should be overridden
var twoMapped = <div />; // Key should be added even if not supplied!
var fourMapped = <div key="keyFour" />;
var fiveMapped = <div />;
var callback = jasmine.createSpy().and.callFake(function(kid, index) {
return index === 0 ? zeroMapped :
index === 1 ? twoMapped :
index === 2 ? fourMapped : fiveMapped;
return index === 0
? zeroMapped
: index === 1 ? twoMapped : index === 2 ? fourMapped : fiveMapped;
});
var frag = ReactFragment.create({
@@ -203,12 +202,7 @@ describe('ReactChildren', () => {
});
var instance = <div>{[frag]}</div>;
expect([
frag[0].key,
frag[1].key,
frag[2].key,
frag[3].key,
]).toEqual([
expect([frag[0].key, frag[1].key, frag[2].key, frag[3].key]).toEqual([
'firstHalfKey/.$keyZero',
'firstHalfKey/.$keyTwo',
'secondHalfKey/.$keyFour',
@@ -244,9 +238,13 @@ describe('ReactChildren', () => {
'.0:$keyFive/.$keyFiveInner',
]);
expect(mappedChildren[0]).toEqual(<div key="giraffe/.0:$firstHalfKey/.$keyZero" />);
expect(mappedChildren[0]).toEqual(
<div key="giraffe/.0:$firstHalfKey/.$keyZero" />,
);
expect(mappedChildren[1]).toEqual(<div key=".0:$firstHalfKey/.$keyTwo" />);
expect(mappedChildren[2]).toEqual(<div key="keyFour/.0:$secondHalfKey/.$keyFour" />);
expect(mappedChildren[2]).toEqual(
<div key="keyFour/.0:$secondHalfKey/.$keyFour" />,
);
expect(mappedChildren[3]).toEqual(<div key=".0:$keyFive/.$keyFiveInner" />);
});
@@ -271,21 +269,24 @@ describe('ReactChildren', () => {
);
var expectedForcedKeys = ['giraffe/.$keyZero', '.$keyOne'];
var mappedChildrenForcedKeys =
ReactChildren.map(forcedKeys.props.children, mapFn);
var mappedForcedKeys = mappedChildrenForcedKeys.map((c) => c.key);
var mappedChildrenForcedKeys = ReactChildren.map(
forcedKeys.props.children,
mapFn,
);
var mappedForcedKeys = mappedChildrenForcedKeys.map(c => c.key);
expect(mappedForcedKeys).toEqual(expectedForcedKeys);
var expectedRemappedForcedKeys = [
'giraffe/.$giraffe/.$keyZero',
'.$.$keyOne',
];
var remappedChildrenForcedKeys =
ReactChildren.map(mappedChildrenForcedKeys, mapFn);
expect(
remappedChildrenForcedKeys.map((c) => c.key)
).toEqual(expectedRemappedForcedKeys);
var remappedChildrenForcedKeys = ReactChildren.map(
mappedChildrenForcedKeys,
mapFn,
);
expect(remappedChildrenForcedKeys.map(c => c.key)).toEqual(
expectedRemappedForcedKeys,
);
});
it('should not throw if key provided is a dupe with array key', () => {
@@ -315,14 +316,10 @@ describe('ReactChildren', () => {
</div>
);
var mapped = ReactChildren.map(
instance.props.children,
element => element,
);
var mapped = ReactChildren.map(instance.props.children, element => element);
var mappedWithClone = ReactChildren.map(
instance.props.children,
element => React.cloneElement(element),
var mappedWithClone = ReactChildren.map(instance.props.children, element =>
React.cloneElement(element),
);
expect(mapped[0].key).toBe(mappedWithClone[0].key);
@@ -335,14 +332,10 @@ describe('ReactChildren', () => {
</div>
);
var mapped = ReactChildren.map(
instance.props.children,
element => element,
);
var mapped = ReactChildren.map(instance.props.children, element => element);
var mappedWithClone = ReactChildren.map(
instance.props.children,
element => React.cloneElement(element, {key: 'unique'}),
var mappedWithClone = ReactChildren.map(instance.props.children, element =>
React.cloneElement(element, {key: 'unique'}),
);
expect(mapped[0].key).toBe(mappedWithClone[0].key);
@@ -399,14 +392,16 @@ describe('ReactChildren', () => {
// 2. If grouped in an Array, the `key` prop, falling back to array index
var instance = (
<div>{[
ReactFragment.create({
firstHalfKey: [zero, one, two],
secondHalfKey: [three, four],
keyFive: five,
}),
null,
]}</div>
<div>
{[
ReactFragment.create({
firstHalfKey: [zero, one, two],
secondHalfKey: [three, four],
keyFive: five,
}),
null,
]}
</div>
);
var numberOfChildren = ReactChildren.count(instance.props.children);
expect(numberOfChildren).toBe(5);
@@ -418,10 +413,8 @@ describe('ReactChildren', () => {
expect(ReactChildren.toArray(<div />).length).toBe(1);
expect(ReactChildren.toArray([<div />]).length).toBe(1);
expect(
ReactChildren.toArray(<div />)[0].key
).toBe(
ReactChildren.toArray([<div />])[0].key
expect(ReactChildren.toArray(<div />)[0].key).toBe(
ReactChildren.toArray([<div />])[0].key,
);
var flattened = ReactChildren.toArray([
@@ -445,9 +438,9 @@ describe('ReactChildren', () => {
expect(flattened[5].key).toBe(reversed[3].key);
// null/undefined/bool are all omitted
expect(ReactChildren.toArray([1, 'two', null, undefined, true])).toEqual(
[1, 'two']
);
expect(ReactChildren.toArray([1, 'two', null, undefined, true])).toEqual([
1,
'two',
]);
});
});
@@ -12,7 +12,6 @@
'use strict';
describe('onlyChild', () => {
var React;
var ReactFragment;
var onlyChild;
@@ -35,63 +34,66 @@ describe('onlyChild', () => {
it('should fail when passed two children', () => {
expect(function() {
var instance =
var instance = (
<WrapComponent>
<div />
<span />
</WrapComponent>;
</WrapComponent>
);
onlyChild(instance.props.children);
}).toThrow();
});
it('should fail when passed nully values', () => {
expect(function() {
var instance =
var instance = (
<WrapComponent>
{null}
</WrapComponent>;
</WrapComponent>
);
onlyChild(instance.props.children);
}).toThrow();
expect(function() {
var instance =
var instance = (
<WrapComponent>
{undefined}
</WrapComponent>;
</WrapComponent>
);
onlyChild(instance.props.children);
}).toThrow();
});
it('should fail when key/value objects', () => {
expect(function() {
var instance =
var instance = (
<WrapComponent>
{ReactFragment.create({oneThing: <span />})}
</WrapComponent>;
</WrapComponent>
);
onlyChild(instance.props.children);
}).toThrow();
});
it('should not fail when passed interpolated single child', () => {
expect(function() {
var instance =
var instance = (
<WrapComponent>
{<span />}
</WrapComponent>;
</WrapComponent>
);
onlyChild(instance.props.children);
}).not.toThrow();
});
it('should return the only child', () => {
expect(function() {
var instance =
var instance = (
<WrapComponent>
<span />
</WrapComponent>;
</WrapComponent>
);
onlyChild(instance.props.children);
}).not.toThrow();
});
});
@@ -12,7 +12,6 @@
'use strict';
describe('sliceChildren', () => {
var React;
var sliceChildren;
@@ -24,11 +23,7 @@ describe('sliceChildren', () => {
});
it('should render the whole set if start zero is supplied', () => {
var fullSet = [
<div key="A" />,
<div key="B" />,
<div key="C" />,
];
var fullSet = [<div key="A" />, <div key="B" />, <div key="C" />];
var children = sliceChildren(fullSet, 0);
expect(children).toEqual([
<div key=".$A" />,
@@ -38,16 +33,9 @@ describe('sliceChildren', () => {
});
it('should render the remaining set if no end index is supplied', () => {
var fullSet = [
<div key="A" />,
<div key="B" />,
<div key="C" />,
];
var fullSet = [<div key="A" />, <div key="B" />, <div key="C" />];
var children = sliceChildren(fullSet, 1);
expect(children).toEqual([
<div key=".$B" />,
<div key=".$C" />,
]);
expect(children).toEqual([<div key=".$B" />, <div key=".$C" />]);
});
it('should exclude everything at or after the end index', () => {
@@ -58,9 +46,7 @@ describe('sliceChildren', () => {
<div key="D" />,
];
var children = sliceChildren(fullSet, 1, 2);
expect(children).toEqual([
<div key=".$B" />,
]);
expect(children).toEqual([<div key=".$B" />]);
});
it('should allow static children to be sliced', () => {
@@ -70,24 +56,16 @@ describe('sliceChildren', () => {
var el = <div>{a}{b}{c}</div>;
var children = sliceChildren(el.props.children, 1, 2);
expect(children).toEqual([
<b key=".1" />,
]);
expect(children).toEqual([<b key=".1" />]);
});
it('should slice nested children', () => {
var fullSet = [
<div key="A" />,
[
<div key="B" />,
<div key="C" />,
],
[<div key="B" />, <div key="C" />],
<div key="D" />,
];
var children = sliceChildren(fullSet, 1, 2);
expect(children).toEqual([
<div key=".1:$B" />,
]);
expect(children).toEqual([<div key=".1:$B" />]);
});
});
+1 -1
View File
@@ -31,7 +31,7 @@ var invariant = require('invariant');
function onlyChild(children) {
invariant(
ReactElement.isValidElement(children),
'React.Children.only expected to receive a single React element child.'
'React.Children.only expected to receive a single React element child.',
);
return children;
}
@@ -67,8 +67,12 @@ describe('ReactContextValidator', () => {
bar: React.PropTypes.number,
};
var instance = ReactTestUtils.renderIntoDocument(<ComponentInFooBarContext />);
reactComponentExpect(instance).expectRenderedChild().scalarContextEqual({foo: 'abc'});
var instance = ReactTestUtils.renderIntoDocument(
<ComponentInFooBarContext />,
);
reactComponentExpect(instance)
.expectRenderedChild()
.scalarContextEqual({foo: 'abc'});
});
it('should filter context properly in callbacks', () => {
@@ -121,7 +125,6 @@ describe('ReactContextValidator', () => {
foo: React.PropTypes.string,
};
var container = document.createElement('div');
ReactDOM.render(<Parent foo="abc" />, container);
ReactDOM.render(<Parent foo="def" />, container);
@@ -148,9 +151,9 @@ describe('ReactContextValidator', () => {
expect(console.error.calls.count()).toBe(1);
expect(normalizeCodeLocInfo(console.error.calls.argsFor(0)[0])).toBe(
'Warning: Failed context type: ' +
'The context `foo` is marked as required in `Component`, but its value ' +
'is `undefined`.\n' +
' in Component (at **)'
'The context `foo` is marked as required in `Component`, but its value ' +
'is `undefined`.\n' +
' in Component (at **)',
);
class ComponentInFooStringContext extends React.Component {
@@ -169,7 +172,7 @@ describe('ReactContextValidator', () => {
};
ReactTestUtils.renderIntoDocument(
<ComponentInFooStringContext fooValue={'bar'} />
<ComponentInFooStringContext fooValue={'bar'} />,
);
// Previous call should not error
@@ -190,15 +193,17 @@ describe('ReactContextValidator', () => {
foo: React.PropTypes.number,
};
ReactTestUtils.renderIntoDocument(<ComponentInFooNumberContext fooValue={123} />);
ReactTestUtils.renderIntoDocument(
<ComponentInFooNumberContext fooValue={123} />,
);
expect(console.error.calls.count()).toBe(2);
expect(normalizeCodeLocInfo(console.error.calls.argsFor(1)[0])).toBe(
'Warning: Failed context type: ' +
'Invalid context `foo` of type `number` supplied ' +
'to `Component`, expected `string`.\n' +
' in Component (at **)\n' +
' in ComponentInFooNumberContext (at **)'
'Invalid context `foo` of type `number` supplied ' +
'to `Component`, expected `string`.\n' +
' in Component (at **)\n' +
' in ComponentInFooNumberContext (at **)',
);
});
@@ -223,9 +228,9 @@ describe('ReactContextValidator', () => {
expect(console.error.calls.count()).toBe(1);
expect(normalizeCodeLocInfo(console.error.calls.argsFor(0)[0])).toBe(
'Warning: Failed child context type: ' +
'The child context `foo` is marked as required in `Component`, but its ' +
'value is `undefined`.\n' +
' in Component (at **)'
'The child context `foo` is marked as required in `Component`, but its ' +
'value is `undefined`.\n' +
' in Component (at **)',
);
ReactTestUtils.renderIntoDocument(<Component testContext={{foo: 123}} />);
@@ -233,21 +238,18 @@ describe('ReactContextValidator', () => {
expect(console.error.calls.count()).toBe(2);
expect(normalizeCodeLocInfo(console.error.calls.argsFor(1)[0])).toBe(
'Warning: Failed child context type: ' +
'Invalid child context `foo` of type `number` ' +
'supplied to `Component`, expected `string`.\n' +
' in Component (at **)'
'Invalid child context `foo` of type `number` ' +
'supplied to `Component`, expected `string`.\n' +
' in Component (at **)',
);
ReactTestUtils.renderIntoDocument(
<Component testContext={{foo: 'foo', bar: 123}} />
<Component testContext={{foo: 'foo', bar: 123}} />,
);
ReactTestUtils.renderIntoDocument(
<Component testContext={{foo: 'foo'}} />
);
ReactTestUtils.renderIntoDocument(<Component testContext={{foo: 'foo'}} />);
// Previous calls should not log errors
expect(console.error.calls.count()).toBe(2);
});
});
+77 -112
View File
@@ -20,7 +20,7 @@ var emptyObject = require('emptyObject');
var invariant = require('invariant');
var warning = require('warning');
import type { ReactPropTypeLocations } from 'ReactPropTypeLocations';
import type {ReactPropTypeLocations} from 'ReactPropTypeLocations';
var MIXINS_KEY = 'mixins';
@@ -37,23 +37,19 @@ type SpecPolicy =
/**
* These methods may be defined only once by the class specification or mixin.
*/
'DEFINE_ONCE' |
/**
| 'DEFINE_ONCE' /**
* These methods may be defined by both the class specification and mixins.
* Subsequent definitions will be chained. These methods must return void.
*/
'DEFINE_MANY' |
/**
| 'DEFINE_MANY' /**
* These methods are overriding the base class.
*/
'OVERRIDE_BASE' |
/**
| 'OVERRIDE_BASE' /**
* These methods are similar to DEFINE_MANY, except we assume they return
* objects. We try to merge the keys of the return values of all the mixed in
* functions. If there is a key conflict we throw.
*/
'DEFINE_MANY_MERGED';
| 'DEFINE_MANY_MERGED';
var injectedMixins = [];
@@ -80,7 +76,6 @@ var injectedMixins = [];
* @internal
*/
var ReactClassInterface: {[key: string]: SpecPolicy} = {
/**
* An array of Mixin objects to include when defining your component.
*
@@ -175,8 +170,6 @@ var ReactClassInterface: {[key: string]: SpecPolicy} = {
*/
render: 'DEFINE_ONCE',
// ==== Delegate methods ====
/**
@@ -287,8 +280,6 @@ var ReactClassInterface: {[key: string]: SpecPolicy} = {
*/
componentWillUnmount: 'DEFINE_MANY',
// ==== Advanced methods ====
/**
@@ -302,7 +293,6 @@ var ReactClassInterface: {[key: string]: SpecPolicy} = {
* @overridable
*/
updateComponent: 'OVERRIDE_BASE',
};
/**
@@ -327,30 +317,22 @@ var RESERVED_SPEC_KEYS = {
},
childContextTypes: function(Constructor, childContextTypes) {
if (__DEV__) {
validateTypeDef(
Constructor,
childContextTypes,
'childContext'
);
validateTypeDef(Constructor, childContextTypes, 'childContext');
}
Constructor.childContextTypes = Object.assign(
{},
Constructor.childContextTypes,
childContextTypes
childContextTypes,
);
},
contextTypes: function(Constructor, contextTypes) {
if (__DEV__) {
validateTypeDef(
Constructor,
contextTypes,
'context'
);
validateTypeDef(Constructor, contextTypes, 'context');
}
Constructor.contextTypes = Object.assign(
{},
Constructor.contextTypes,
contextTypes
contextTypes,
);
},
/**
@@ -361,7 +343,7 @@ var RESERVED_SPEC_KEYS = {
if (Constructor.getDefaultProps) {
Constructor.getDefaultProps = createMergedResultFunction(
Constructor.getDefaultProps,
getDefaultProps
getDefaultProps,
);
} else {
Constructor.getDefaultProps = getDefaultProps;
@@ -369,17 +351,9 @@ var RESERVED_SPEC_KEYS = {
},
propTypes: function(Constructor, propTypes) {
if (__DEV__) {
validateTypeDef(
Constructor,
propTypes,
'prop'
);
validateTypeDef(Constructor, propTypes, 'prop');
}
Constructor.propTypes = Object.assign(
{},
Constructor.propTypes,
propTypes
);
Constructor.propTypes = Object.assign({}, Constructor.propTypes, propTypes);
},
statics: function(Constructor, statics) {
mixStaticSpecIntoComponent(Constructor, statics);
@@ -399,40 +373,39 @@ function validateTypeDef(
warning(
typeof typeDef[propName] === 'function',
'%s: %s type `%s` is invalid; it must be a function, usually from ' +
'React.PropTypes.',
'React.PropTypes.',
Constructor.displayName || 'ReactClass',
ReactPropTypeLocationNames[location],
propName
propName,
);
}
}
}
function validateMethodOverride(isAlreadyDefined, name) {
var specPolicy = ReactClassInterface.hasOwnProperty(name) ?
ReactClassInterface[name] :
null;
var specPolicy = ReactClassInterface.hasOwnProperty(name)
? ReactClassInterface[name]
: null;
// Disallow overriding of base class methods unless explicitly allowed.
if (ReactClassMixin.hasOwnProperty(name)) {
invariant(
specPolicy === 'OVERRIDE_BASE',
'ReactClassInterface: You are attempting to override ' +
'`%s` from your class specification. Ensure that your method names ' +
'do not overlap with React methods.',
name
'`%s` from your class specification. Ensure that your method names ' +
'do not overlap with React methods.',
name,
);
}
// Disallow defining methods more than once unless explicitly allowed.
if (isAlreadyDefined) {
invariant(
specPolicy === 'DEFINE_MANY' ||
specPolicy === 'DEFINE_MANY_MERGED',
specPolicy === 'DEFINE_MANY' || specPolicy === 'DEFINE_MANY_MERGED',
'ReactClassInterface: You are attempting to define ' +
'`%s` on your component more than once. This conflict may be due ' +
'to a mixin.',
name
'`%s` on your component more than once. This conflict may be due ' +
'to a mixin.',
name,
);
}
}
@@ -449,12 +422,12 @@ function mixSpecIntoComponent(Constructor, spec) {
warning(
isMixinValid,
'%s: You\'re attempting to include a mixin that is either null ' +
'or not an object. Check the mixins included by the component, ' +
'as well as any mixins they include themselves. ' +
'Expected object but got %s.',
"%s: You're attempting to include a mixin that is either null " +
'or not an object. Check the mixins included by the component, ' +
'as well as any mixins they include themselves. ' +
'Expected object but got %s.',
Constructor.displayName || 'ReactClass',
spec === null ? null : typeofSpec
spec === null ? null : typeofSpec,
);
}
@@ -463,14 +436,14 @@ function mixSpecIntoComponent(Constructor, spec) {
invariant(
typeof spec !== 'function',
'ReactClass: You\'re attempting to ' +
'use a component class or function as a mixin. Instead, just use a ' +
'regular object.'
"ReactClass: You're attempting to " +
'use a component class or function as a mixin. Instead, just use a ' +
'regular object.',
);
invariant(
!ReactElement.isValidElement(spec),
'ReactClass: You\'re attempting to ' +
'use a component as a mixin. Instead, just use a regular object.'
"ReactClass: You're attempting to " +
'use a component as a mixin. Instead, just use a regular object.',
);
var proto = Constructor.prototype;
@@ -504,8 +477,7 @@ function mixSpecIntoComponent(Constructor, spec) {
// The following member methods should not be automatically bound:
// 1. Expected ReactClass methods (in the "interface").
// 2. Overridden methods (that were mixed in).
var isReactClassMethod =
ReactClassInterface.hasOwnProperty(name);
var isReactClassMethod = ReactClassInterface.hasOwnProperty(name);
var isFunction = typeof property === 'function';
var shouldAutoBind =
isFunction &&
@@ -522,14 +494,13 @@ function mixSpecIntoComponent(Constructor, spec) {
// These cases should already be caught by validateMethodOverride.
invariant(
isReactClassMethod && (
specPolicy === 'DEFINE_MANY_MERGED' ||
specPolicy === 'DEFINE_MANY'
),
isReactClassMethod &&
(specPolicy === 'DEFINE_MANY_MERGED' ||
specPolicy === 'DEFINE_MANY'),
'ReactClass: Unexpected spec policy %s for key %s ' +
'when mixing in component specs.',
'when mixing in component specs.',
specPolicy,
name
name,
);
// For methods which are defined more than once, call the existing
@@ -568,19 +539,19 @@ function mixStaticSpecIntoComponent(Constructor, statics) {
invariant(
!isReserved,
'ReactClass: You are attempting to define a reserved ' +
'property, `%s`, that shouldn\'t be on the "statics" key. Define it ' +
'as an instance property instead; it will still be accessible on the ' +
'constructor.',
name
'property, `%s`, that shouldn\'t be on the "statics" key. Define it ' +
'as an instance property instead; it will still be accessible on the ' +
'constructor.',
name,
);
var isInherited = name in Constructor;
invariant(
!isInherited,
'ReactClass: You are attempting to define ' +
'`%s` on your component more than once. This conflict may be ' +
'due to a mixin.',
name
'`%s` on your component more than once. This conflict may be ' +
'due to a mixin.',
name,
);
Constructor[name] = property;
}
@@ -596,7 +567,7 @@ function mixStaticSpecIntoComponent(Constructor, statics) {
function mergeIntoWithNoDuplicateKeys(one, two) {
invariant(
one && two && typeof one === 'object' && typeof two === 'object',
'mergeIntoWithNoDuplicateKeys(): Cannot merge non-objects.'
'mergeIntoWithNoDuplicateKeys(): Cannot merge non-objects.',
);
for (var key in two) {
@@ -604,11 +575,11 @@ function mergeIntoWithNoDuplicateKeys(one, two) {
invariant(
one[key] === undefined,
'mergeIntoWithNoDuplicateKeys(): ' +
'Tried to merge two objects with the same key: `%s`. This conflict ' +
'may be due to a mixin; in particular, this may be caused by two ' +
'getInitialState() or getDefaultProps() methods returning objects ' +
'with clashing keys.',
key
'Tried to merge two objects with the same key: `%s`. This conflict ' +
'may be due to a mixin; in particular, this may be caused by two ' +
'getInitialState() or getDefaultProps() methods returning objects ' +
'with clashing keys.',
key,
);
one[key] = two[key];
}
@@ -678,16 +649,16 @@ function bindAutoBindMethod(component, method) {
warning(
false,
'bind(): React component methods may only be bound to the ' +
'component instance. See %s',
componentName
'component instance. See %s',
componentName,
);
} else if (!args.length) {
warning(
false,
'bind(): You are binding a component method to the component. ' +
'React does this for you automatically in a high-performance ' +
'way, so you can safely remove this call. See %s',
componentName
'React does this for you automatically in a high-performance ' +
'way, so you can safely remove this call. See %s',
componentName,
);
return boundMethod;
}
@@ -711,10 +682,7 @@ function bindAutoBindMethods(component) {
for (var i = 0; i < pairs.length; i += 2) {
var autoBindKey = pairs[i];
var method = pairs[i + 1];
component[autoBindKey] = bindAutoBindMethod(
component,
method
);
component[autoBindKey] = bindAutoBindMethod(component, method);
}
}
@@ -723,7 +691,6 @@ function bindAutoBindMethods(component) {
* therefore not already part of the modern ReactComponent.
*/
var ReactClassMixin = {
/**
* TODO: This will be deprecated because state should always keep a consistent
* type signature and the only use case for this, is to avoid that.
@@ -750,7 +717,7 @@ var ReactClassComponent = function() {};
Object.assign(
ReactClassComponent.prototype,
ReactComponent.prototype,
ReactClassMixin
ReactClassMixin,
);
let didWarnDeprecated = false;
@@ -761,7 +728,6 @@ let didWarnDeprecated = false;
* @class ReactClass
*/
var ReactClass = {
/**
* Creates a composite component class given a class specification.
* See https://facebook.github.io/react/docs/top-level-api.html#react.createclass
@@ -775,9 +741,9 @@ var ReactClass = {
warning(
didWarnDeprecated,
'%s: React.createClass is deprecated and will be removed in version 16. ' +
'Use plain JavaScript classes instead. If you\'re not yet ready to ' +
'migrate, create-react-class is available on npm as a ' +
'drop-in replacement.',
"Use plain JavaScript classes instead. If you're not yet ready to " +
'migrate, create-react-class is available on npm as a ' +
'drop-in replacement.',
(spec && spec.displayName) || 'A Component',
);
didWarnDeprecated = true;
@@ -794,7 +760,7 @@ var ReactClass = {
warning(
this instanceof Constructor,
'Something is calling a React component directly. Use a factory or ' +
'JSX instead. See: https://fb.me/react-legacyfactory'
'JSX instead. See: https://fb.me/react-legacyfactory',
);
}
@@ -816,8 +782,10 @@ var ReactClass = {
var initialState = this.getInitialState ? this.getInitialState() : null;
if (__DEV__) {
// We allow auto-mocks to proceed as if they're returning null.
if (initialState === undefined &&
this.getInitialState._isMockFunction) {
if (
initialState === undefined &&
this.getInitialState._isMockFunction
) {
// This is probably bad practice. Consider warning here and
// deprecating this convenience.
initialState = null;
@@ -826,7 +794,7 @@ var ReactClass = {
invariant(
typeof initialState === 'object' && !Array.isArray(initialState),
'%s.getInitialState(): must return an object or null',
Constructor.displayName || 'ReactCompositeComponent'
Constructor.displayName || 'ReactCompositeComponent',
);
this.state = initialState;
@@ -835,9 +803,7 @@ var ReactClass = {
Constructor.prototype.constructor = Constructor;
Constructor.prototype.__reactAutoBindPairs = [];
injectedMixins.forEach(
mixSpecIntoComponent.bind(null, Constructor)
);
injectedMixins.forEach(mixSpecIntoComponent.bind(null, Constructor));
mixSpecIntoComponent(Constructor, spec);
@@ -861,23 +827,23 @@ var ReactClass = {
invariant(
Constructor.prototype.render,
'createClass(...): Class specification must implement a `render` method.'
'createClass(...): Class specification must implement a `render` method.',
);
if (__DEV__) {
warning(
!Constructor.prototype.componentShouldUpdate,
'%s has a method called ' +
'componentShouldUpdate(). Did you mean shouldComponentUpdate()? ' +
'The name is phrased as a question because the function is ' +
'expected to return a value.',
spec.displayName || 'A component'
'componentShouldUpdate(). Did you mean shouldComponentUpdate()? ' +
'The name is phrased as a question because the function is ' +
'expected to return a value.',
spec.displayName || 'A component',
);
warning(
!Constructor.prototype.componentWillRecieveProps,
'%s has a method called ' +
'componentWillRecieveProps(). Did you mean componentWillReceiveProps()?',
spec.displayName || 'A component'
'componentWillRecieveProps(). Did you mean componentWillReceiveProps()?',
spec.displayName || 'A component',
);
}
@@ -896,7 +862,6 @@ var ReactClass = {
injectedMixins.push(mixin);
},
},
};
module.exports = ReactClass;
@@ -16,7 +16,6 @@ var ReactDOM;
var ReactTestUtils;
describe('ReactClass-spec', () => {
beforeEach(() => {
React = require('React');
ReactDOM = require('ReactDOM');
@@ -37,9 +36,9 @@ describe('ReactClass-spec', () => {
expect(console.error.calls.count()).toEqual(1);
expect(console.error.calls.argsFor(0)[0]).toBe(
'Warning: MyComponent: React.createClass is deprecated and will be removed in ' +
'version 16. Use plain JavaScript classes instead. If you\'re not yet ' +
'ready to migrate, create-react-class is available on npm as a ' +
'drop-in replacement.'
"version 16. Use plain JavaScript classes instead. If you're not yet " +
'ready to migrate, create-react-class is available on npm as a ' +
'drop-in replacement.',
);
console.error.calls.reset();
});
@@ -48,7 +47,7 @@ describe('ReactClass-spec', () => {
expect(function() {
React.createClass({});
}).toThrowError(
'createClass(...): Class specification must implement a `render` method.'
'createClass(...): Class specification must implement a `render` method.',
);
});
@@ -59,8 +58,7 @@ describe('ReactClass-spec', () => {
},
});
expect(TestComponent.displayName)
.toBe('TestComponent');
expect(TestComponent.displayName).toBe('TestComponent');
});
it('should copy prop types onto the Constructor', () => {
@@ -75,8 +73,7 @@ describe('ReactClass-spec', () => {
});
expect(TestComponent.propTypes).toBeDefined();
expect(TestComponent.propTypes.value)
.toBe(propValidator);
expect(TestComponent.propTypes.value).toBe(propValidator);
});
it('should warn on invalid prop types', () => {
@@ -93,7 +90,7 @@ describe('ReactClass-spec', () => {
expect(console.error.calls.count()).toBe(1);
expect(console.error.calls.argsFor(0)[0]).toBe(
'Warning: Component: prop type `prop` is invalid; ' +
'it must be a function, usually from React.PropTypes.'
'it must be a function, usually from React.PropTypes.',
);
});
@@ -111,7 +108,7 @@ describe('ReactClass-spec', () => {
expect(console.error.calls.count()).toBe(1);
expect(console.error.calls.argsFor(0)[0]).toBe(
'Warning: Component: context type `prop` is invalid; ' +
'it must be a function, usually from React.PropTypes.'
'it must be a function, usually from React.PropTypes.',
);
});
@@ -129,7 +126,7 @@ describe('ReactClass-spec', () => {
expect(console.error.calls.count()).toBe(1);
expect(console.error.calls.argsFor(0)[0]).toBe(
'Warning: Component: child context type `prop` is invalid; ' +
'it must be a function, usually from React.PropTypes.'
'it must be a function, usually from React.PropTypes.',
);
});
@@ -147,8 +144,8 @@ describe('ReactClass-spec', () => {
expect(console.error.calls.count()).toBe(1);
expect(console.error.calls.argsFor(0)[0]).toBe(
'Warning: A component has a method called componentShouldUpdate(). Did you ' +
'mean shouldComponentUpdate()? The name is phrased as a question ' +
'because the function is expected to return a value.'
'mean shouldComponentUpdate()? The name is phrased as a question ' +
'because the function is expected to return a value.',
);
React.createClass({
@@ -163,8 +160,8 @@ describe('ReactClass-spec', () => {
expect(console.error.calls.count()).toBe(2);
expect(console.error.calls.argsFor(1)[0]).toBe(
'Warning: NamedComponent has a method called componentShouldUpdate(). Did you ' +
'mean shouldComponentUpdate()? The name is phrased as a question ' +
'because the function is expected to return a value.'
'mean shouldComponentUpdate()? The name is phrased as a question ' +
'because the function is expected to return a value.',
);
});
@@ -181,7 +178,7 @@ describe('ReactClass-spec', () => {
expect(console.error.calls.count()).toBe(1);
expect(console.error.calls.argsFor(0)[0]).toBe(
'Warning: A component has a method called componentWillRecieveProps(). Did you ' +
'mean componentWillReceiveProps()?'
'mean componentWillReceiveProps()?',
);
});
@@ -202,9 +199,9 @@ describe('ReactClass-spec', () => {
});
}).toThrowError(
'ReactClass: You are attempting to define a reserved property, ' +
'`getDefaultProps`, that shouldn\'t be on the "statics" key. Define ' +
'it as an instance property instead; it will still be accessible on ' +
'the constructor.'
'`getDefaultProps`, that shouldn\'t be on the "statics" key. Define ' +
'it as an instance property instead; it will still be accessible on ' +
'the constructor.',
);
});
@@ -230,19 +227,19 @@ describe('ReactClass-spec', () => {
expect(console.error.calls.count()).toBe(4);
expect(console.error.calls.argsFor(0)[0]).toBe(
'createClass(...): `mixins` is now a static property and should ' +
'be defined inside "statics".'
'be defined inside "statics".',
);
expect(console.error.calls.argsFor(1)[0]).toBe(
'createClass(...): `propTypes` is now a static property and should ' +
'be defined inside "statics".'
'be defined inside "statics".',
);
expect(console.error.calls.argsFor(2)[0]).toBe(
'createClass(...): `contextTypes` is now a static property and ' +
'should be defined inside "statics".'
'should be defined inside "statics".',
);
expect(console.error.calls.argsFor(3)[0]).toBe(
'createClass(...): `childContextTypes` is now a static property and ' +
'should be defined inside "statics".'
'should be defined inside "statics".',
);
});
@@ -336,7 +333,7 @@ describe('ReactClass-spec', () => {
expect(function() {
instance = ReactTestUtils.renderIntoDocument(instance);
}).toThrowError(
'Component.getInitialState(): must return an object or null'
'Component.getInitialState(): must return an object or null',
);
});
});
@@ -350,8 +347,8 @@ describe('ReactClass-spec', () => {
return <span />;
},
});
expect(
() => ReactTestUtils.renderIntoDocument(<Component />)
expect(() =>
ReactTestUtils.renderIntoDocument(<Component />),
).not.toThrow();
});
@@ -367,8 +364,7 @@ describe('ReactClass-spec', () => {
expect(console.error.calls.count()).toBe(1);
expect(console.error.calls.argsFor(0)[0]).toBe(
'Warning: Something is calling a React component directly. Use a ' +
'factory or JSX instead. See: https://fb.me/react-legacyfactory'
'factory or JSX instead. See: https://fb.me/react-legacyfactory',
);
});
});
@@ -17,7 +17,6 @@ var ReactTestUtils;
var createReactClass;
describe('ReactClass-spec', () => {
beforeEach(() => {
React = require('React');
ReactDOM = require('ReactDOM');
@@ -34,7 +33,7 @@ describe('ReactClass-spec', () => {
expect(function() {
createReactClass({});
}).toThrowError(
'createClass(...): Class specification must implement a `render` method.'
'createClass(...): Class specification must implement a `render` method.',
);
});
@@ -46,8 +45,7 @@ describe('ReactClass-spec', () => {
},
});
expect(TestComponent.displayName)
.toBe('TestComponent');
expect(TestComponent.displayName).toBe('TestComponent');
});
it('should copy prop types onto the Constructor', () => {
@@ -62,8 +60,7 @@ describe('ReactClass-spec', () => {
});
expect(TestComponent.propTypes).toBeDefined();
expect(TestComponent.propTypes.value)
.toBe(propValidator);
expect(TestComponent.propTypes.value).toBe(propValidator);
});
it('should warn on invalid prop types', () => {
@@ -80,7 +77,7 @@ describe('ReactClass-spec', () => {
expect(console.error.calls.count()).toBe(1);
expect(console.error.calls.argsFor(0)[0]).toBe(
'Warning: Component: prop type `prop` is invalid; ' +
'it must be a function, usually from React.PropTypes.'
'it must be a function, usually from React.PropTypes.',
);
});
@@ -98,7 +95,7 @@ describe('ReactClass-spec', () => {
expect(console.error.calls.count()).toBe(1);
expect(console.error.calls.argsFor(0)[0]).toBe(
'Warning: Component: context type `prop` is invalid; ' +
'it must be a function, usually from React.PropTypes.'
'it must be a function, usually from React.PropTypes.',
);
});
@@ -116,7 +113,7 @@ describe('ReactClass-spec', () => {
expect(console.error.calls.count()).toBe(1);
expect(console.error.calls.argsFor(0)[0]).toBe(
'Warning: Component: child context type `prop` is invalid; ' +
'it must be a function, usually from React.PropTypes.'
'it must be a function, usually from React.PropTypes.',
);
});
@@ -134,8 +131,8 @@ describe('ReactClass-spec', () => {
expect(console.error.calls.count()).toBe(1);
expect(console.error.calls.argsFor(0)[0]).toBe(
'Warning: A component has a method called componentShouldUpdate(). Did you ' +
'mean shouldComponentUpdate()? The name is phrased as a question ' +
'because the function is expected to return a value.'
'mean shouldComponentUpdate()? The name is phrased as a question ' +
'because the function is expected to return a value.',
);
createReactClass({
@@ -150,8 +147,8 @@ describe('ReactClass-spec', () => {
expect(console.error.calls.count()).toBe(2);
expect(console.error.calls.argsFor(1)[0]).toBe(
'Warning: NamedComponent has a method called componentShouldUpdate(). Did you ' +
'mean shouldComponentUpdate()? The name is phrased as a question ' +
'because the function is expected to return a value.'
'mean shouldComponentUpdate()? The name is phrased as a question ' +
'because the function is expected to return a value.',
);
});
@@ -168,7 +165,7 @@ describe('ReactClass-spec', () => {
expect(console.error.calls.count()).toBe(1);
expect(console.error.calls.argsFor(0)[0]).toBe(
'Warning: A component has a method called componentWillRecieveProps(). Did you ' +
'mean componentWillReceiveProps()?'
'mean componentWillReceiveProps()?',
);
});
@@ -189,9 +186,9 @@ describe('ReactClass-spec', () => {
});
}).toThrowError(
'ReactClass: You are attempting to define a reserved property, ' +
'`getDefaultProps`, that shouldn\'t be on the "statics" key. Define ' +
'it as an instance property instead; it will still be accessible on ' +
'the constructor.'
'`getDefaultProps`, that shouldn\'t be on the "statics" key. Define ' +
'it as an instance property instead; it will still be accessible on ' +
'the constructor.',
);
});
@@ -217,19 +214,19 @@ describe('ReactClass-spec', () => {
expect(console.error.calls.count()).toBe(4);
expect(console.error.calls.argsFor(0)[0]).toBe(
'createClass(...): `mixins` is now a static property and should ' +
'be defined inside "statics".'
'be defined inside "statics".',
);
expect(console.error.calls.argsFor(1)[0]).toBe(
'createClass(...): `propTypes` is now a static property and should ' +
'be defined inside "statics".'
'be defined inside "statics".',
);
expect(console.error.calls.argsFor(2)[0]).toBe(
'createClass(...): `contextTypes` is now a static property and ' +
'should be defined inside "statics".'
'should be defined inside "statics".',
);
expect(console.error.calls.argsFor(3)[0]).toBe(
'createClass(...): `childContextTypes` is now a static property and ' +
'should be defined inside "statics".'
'should be defined inside "statics".',
);
});
@@ -323,7 +320,7 @@ describe('ReactClass-spec', () => {
expect(function() {
instance = ReactTestUtils.renderIntoDocument(instance);
}).toThrowError(
'Component.getInitialState(): must return an object or null'
'Component.getInitialState(): must return an object or null',
);
});
});
@@ -337,8 +334,8 @@ describe('ReactClass-spec', () => {
return <span />;
},
});
expect(
() => ReactTestUtils.renderIntoDocument(<Component />)
expect(() =>
ReactTestUtils.renderIntoDocument(<Component />),
).not.toThrow();
});
@@ -354,7 +351,7 @@ describe('ReactClass-spec', () => {
expect(console.error.calls.count()).toBe(1);
expect(console.error.calls.argsFor(0)[0]).toBe(
'Warning: Something is calling a React component directly. Use a ' +
'factory or JSX instead. See: https://fb.me/react-legacyfactory'
'factory or JSX instead. See: https://fb.me/react-legacyfactory',
);
});
@@ -362,7 +359,7 @@ describe('ReactClass-spec', () => {
var ops = [];
var Component = createReactClass({
getInitialState() {
return { step: 0 };
return {step: 0};
},
render() {
ops.push('Render: ' + this.state.step);
@@ -371,14 +368,10 @@ describe('ReactClass-spec', () => {
});
var instance = ReactTestUtils.renderIntoDocument(<Component />);
instance.replaceState({ step: 1 }, () => {
instance.replaceState({step: 1}, () => {
ops.push('Callback: ' + instance.state.step);
});
expect(ops).toEqual([
'Render: 0',
'Render: 1',
'Callback: 1',
]);
expect(ops).toEqual(['Render: 0', 'Render: 1', 'Callback: 1']);
});
it('isMounted works', () => {
@@ -437,8 +430,8 @@ describe('ReactClass-spec', () => {
expect(console.error.calls.count()).toBe(1);
expect(console.error.calls.argsFor(0)[0]).toEqual(
'Warning: MyComponent: isMounted is deprecated. Instead, make sure to ' +
'clean up subscriptions and pending requests in componentWillUnmount ' +
'to prevent memory leaks.'
'clean up subscriptions and pending requests in componentWillUnmount ' +
'to prevent memory leaks.',
);
});
});
@@ -12,7 +12,7 @@
'use strict';
import type { ReactInstance } from 'ReactInstanceType';
import type {ReactInstance} from 'ReactInstanceType';
/**
* Keeps track of the current owner.
@@ -21,13 +21,11 @@ import type { ReactInstance } from 'ReactInstanceType';
* currently being constructed.
*/
var ReactCurrentOwner = {
/**
* @internal
* @type {ReactComponent}
*/
current: (null: null | ReactInstance),
};
module.exports = ReactCurrentOwner;
@@ -141,7 +141,7 @@ var ReactDOMFactories = {
track: createDOMFactory('track'),
u: createDOMFactory('u'),
ul: createDOMFactory('ul'),
'var': createDOMFactory('var'),
var: createDOMFactory('var'),
video: createDOMFactory('video'),
wbr: createDOMFactory('wbr'),
+26 -28
View File
@@ -59,10 +59,10 @@ function defineKeyPropWarningGetter(props, displayName) {
warning(
false,
'%s: `key` is not a prop. Trying to access it will result ' +
'in `undefined` being returned. If you need to access the same ' +
'value within the child component, you should pass it as a different ' +
'prop. (https://fb.me/react-special-props)',
displayName
'in `undefined` being returned. If you need to access the same ' +
'value within the child component, you should pass it as a different ' +
'prop. (https://fb.me/react-special-props)',
displayName,
);
}
};
@@ -80,10 +80,10 @@ function defineRefPropWarningGetter(props, displayName) {
warning(
false,
'%s: `ref` is not a prop. Trying to access it will result ' +
'in `undefined` being returned. If you need to access the same ' +
'value within the child component, you should pass it as a different ' +
'prop. (https://fb.me/react-special-props)',
displayName
'in `undefined` being returned. If you need to access the same ' +
'value within the child component, you should pass it as a different ' +
'prop. (https://fb.me/react-special-props)',
displayName,
);
}
};
@@ -203,8 +203,10 @@ ReactElement.createElement = function(type, config, children) {
source = config.__source === undefined ? null : config.__source;
// Remaining properties are added to a new props object
for (propName in config) {
if (hasOwnProperty.call(config, propName) &&
!RESERVED_PROPS.hasOwnProperty(propName)) {
if (
hasOwnProperty.call(config, propName) &&
!RESERVED_PROPS.hasOwnProperty(propName)
) {
props[propName] = config[propName];
}
}
@@ -239,11 +241,13 @@ ReactElement.createElement = function(type, config, children) {
}
if (__DEV__) {
if (key || ref) {
if (typeof props.$$typeof === 'undefined' ||
props.$$typeof !== REACT_ELEMENT_TYPE) {
var displayName = typeof type === 'function' ?
(type.displayName || type.name || 'Unknown') :
type;
if (
typeof props.$$typeof === 'undefined' ||
props.$$typeof !== REACT_ELEMENT_TYPE
) {
var displayName = typeof type === 'function'
? type.displayName || type.name || 'Unknown'
: type;
if (key) {
defineKeyPropWarningGetter(props, displayName);
}
@@ -260,7 +264,7 @@ ReactElement.createElement = function(type, config, children) {
self,
source,
ReactCurrentOwner.current,
props
props,
);
};
@@ -287,7 +291,7 @@ ReactElement.cloneAndReplaceKey = function(oldElement, newKey) {
oldElement._self,
oldElement._source,
oldElement._owner,
oldElement.props
oldElement.props,
);
return newElement;
@@ -332,8 +336,10 @@ ReactElement.cloneElement = function(element, config, children) {
defaultProps = element.type.defaultProps;
}
for (propName in config) {
if (hasOwnProperty.call(config, propName) &&
!RESERVED_PROPS.hasOwnProperty(propName)) {
if (
hasOwnProperty.call(config, propName) &&
!RESERVED_PROPS.hasOwnProperty(propName)
) {
if (config[propName] === undefined && defaultProps !== undefined) {
// Resolve default props
props[propName] = defaultProps[propName];
@@ -357,15 +363,7 @@ ReactElement.cloneElement = function(element, config, children) {
props.children = childArray;
}
return ReactElement(
element.type,
key,
ref,
self,
source,
owner,
props
);
return ReactElement(element.type, key, ref, self, source, owner, props);
};
/**
@@ -12,7 +12,7 @@
'use strict';
import type { ReactInstance } from 'ReactInstanceType';
import type {ReactInstance} from 'ReactInstanceType';
export type Source = {
fileName: string,
@@ -63,8 +63,9 @@ function getCurrentComponentErrorInfo(parentType) {
var info = getDeclarationErrorAddendum();
if (!info) {
var parentName = typeof parentType === 'string' ?
parentType : parentType.displayName || parentType.name;
var parentName = typeof parentType === 'string'
? parentType
: parentType.displayName || parentType.name;
if (parentName) {
info = ` Check the top-level render call using <${parentName}>.`;
}
@@ -89,9 +90,8 @@ function validateExplicitKey(element, parentType) {
}
element._store.validated = true;
var memoizer = ownerHasKeyUseWarning.uniqueKey || (
ownerHasKeyUseWarning.uniqueKey = {}
);
var memoizer =
ownerHasKeyUseWarning.uniqueKey || (ownerHasKeyUseWarning.uniqueKey = {});
var currentComponentErrorInfo = getCurrentComponentErrorInfo(parentType);
if (memoizer[currentComponentErrorInfo]) {
@@ -103,21 +103,22 @@ function validateExplicitKey(element, parentType) {
// property, it may be the creator of the child that's responsible for
// assigning it a key.
var childOwner = '';
if (element &&
element._owner &&
element._owner !== ReactCurrentOwner.current) {
if (
element &&
element._owner &&
element._owner !== ReactCurrentOwner.current
) {
// Give the component that originally created this child.
childOwner =
` It was passed a child from ${element._owner.getName()}.`;
childOwner = ` It was passed a child from ${element._owner.getName()}.`;
}
warning(
false,
'Each child in an array or iterator should have a unique "key" prop.' +
'%s%s See https://fb.me/react-warning-keys for more information.%s',
'%s%s See https://fb.me/react-warning-keys for more information.%s',
currentComponentErrorInfo,
childOwner,
ReactComponentTreeHook.getCurrentStackAddendum(element)
ReactComponentTreeHook.getCurrentStackAddendum(element),
);
}
@@ -182,39 +183,35 @@ function validatePropTypes(element) {
'prop',
name,
element,
null
null,
);
}
if (typeof componentClass.getDefaultProps === 'function') {
warning(
componentClass.getDefaultProps.isReactClassApproved,
'getDefaultProps is only used on classic React.createClass ' +
'definitions. Use a static property named `defaultProps` instead.'
'definitions. Use a static property named `defaultProps` instead.',
);
}
}
var ReactElementValidator = {
createElement: function(type, props, children) {
var validType = typeof type === 'string' || typeof type === 'function';
// We warn in this case but don't throw. We expect the element creation to
// succeed and there will likely be errors in render.
if (!validType) {
if (
typeof type !== 'function' &&
typeof type !== 'string'
) {
if (typeof type !== 'function' && typeof type !== 'string') {
var info = '';
if (
type === undefined ||
typeof type === 'object' &&
type !== null &&
Object.keys(type).length === 0
(typeof type === 'object' &&
type !== null &&
Object.keys(type).length === 0)
) {
info +=
' You likely forgot to export your component from the file ' +
'it\'s defined in.';
"it's defined in.";
}
var sourceInfo = getSourceInfoErrorAddendum(props);
@@ -229,8 +226,8 @@ var ReactElementValidator = {
warning(
false,
'React.createElement: type is invalid -- expected a string (for ' +
'built-in components) or a class/function (for composite ' +
'components) but got: %s.%s',
'built-in components) or a class/function (for composite ' +
'components) but got: %s.%s',
type == null ? type : typeof type,
info,
);
@@ -262,37 +259,29 @@ var ReactElementValidator = {
},
createFactory: function(type) {
var validatedFactory = ReactElementValidator.createElement.bind(
null,
type
);
var validatedFactory = ReactElementValidator.createElement.bind(null, type);
// Legacy hook TODO: Warn if this is accessed
validatedFactory.type = type;
if (__DEV__) {
if (canDefineProperty) {
Object.defineProperty(
validatedFactory,
'type',
{
enumerable: false,
get: function() {
warning(
false,
'Factory.type is deprecated. Access the class directly ' +
'before passing it to createFactory.'
);
Object.defineProperty(this, 'type', {
value: type,
});
return type;
},
}
);
Object.defineProperty(validatedFactory, 'type', {
enumerable: false,
get: function() {
warning(
false,
'Factory.type is deprecated. Access the class directly ' +
'before passing it to createFactory.',
);
Object.defineProperty(this, 'type', {
value: type,
});
return type;
},
});
}
}
return validatedFactory;
},
@@ -304,7 +293,6 @@ var ReactElementValidator = {
validatePropTypes(newElement);
return newElement;
},
};
module.exports = ReactElementValidator;
@@ -81,9 +81,9 @@ describe('ReactElement', () => {
expect(console.error.calls.count()).toBe(1);
expect(console.error.calls.argsFor(0)[0]).toContain(
'Child: `key` is not a prop. Trying to access it will result ' +
'in `undefined` being returned. If you need to access the same ' +
'value within the child component, you should pass it as a different ' +
'prop. (https://fb.me/react-special-props)'
'in `undefined` being returned. If you need to access the same ' +
'value within the child component, you should pass it as a different ' +
'prop. (https://fb.me/react-special-props)',
);
});
@@ -95,9 +95,9 @@ describe('ReactElement', () => {
expect(console.error.calls.count()).toBe(1);
expect(console.error.calls.argsFor(0)[0]).toContain(
'div: `key` is not a prop. Trying to access it will result ' +
'in `undefined` being returned. If you need to access the same ' +
'value within the child component, you should pass it as a different ' +
'prop. (https://fb.me/react-special-props)'
'in `undefined` being returned. If you need to access the same ' +
'value within the child component, you should pass it as a different ' +
'prop. (https://fb.me/react-special-props)',
);
});
@@ -123,9 +123,9 @@ describe('ReactElement', () => {
expect(console.error.calls.count()).toBe(1);
expect(console.error.calls.argsFor(0)[0]).toContain(
'Child: `ref` is not a prop. Trying to access it will result ' +
'in `undefined` being returned. If you need to access the same ' +
'value within the child component, you should pass it as a different ' +
'prop. (https://fb.me/react-special-props)'
'in `undefined` being returned. If you need to access the same ' +
'value within the child component, you should pass it as a different ' +
'prop. (https://fb.me/react-special-props)',
);
});
@@ -141,7 +141,7 @@ describe('ReactElement', () => {
it('returns an immutable element', () => {
var element = React.createFactory(ComponentClass)();
expect(() => element.type = 'div').toThrow();
expect(() => (element.type = 'div')).toThrow();
});
it('does not reuse the original config object', () => {
@@ -233,7 +233,7 @@ describe('ReactElement', () => {
}
var instance = ReactTestUtils.renderIntoDocument(
React.createElement(Wrapper)
React.createElement(Wrapper),
);
expect(element._owner.getPublicInstance()).toBe(instance);
@@ -242,9 +242,12 @@ describe('ReactElement', () => {
it('merges an additional argument onto the children prop', () => {
spyOn(console, 'error');
var a = 1;
var element = React.createFactory(ComponentClass)({
children: 'text',
}, a);
var element = React.createFactory(ComponentClass)(
{
children: 'text',
},
a,
);
expect(element.props.children).toBe(a);
expect(console.error.calls.count()).toBe(0);
});
@@ -260,9 +263,12 @@ describe('ReactElement', () => {
it('overrides children if null is provided as an argument', () => {
spyOn(console, 'error');
var element = React.createFactory(ComponentClass)({
children: 'text',
}, null);
var element = React.createFactory(ComponentClass)(
{
children: 'text',
},
null,
);
expect(element.props.children).toBe(null);
expect(console.error.calls.count()).toBe(0);
});
@@ -303,10 +309,8 @@ describe('ReactElement', () => {
}
}
expect(React.isValidElement(React.createElement('div')))
.toEqual(true);
expect(React.isValidElement(React.createElement(Component)))
.toEqual(true);
expect(React.isValidElement(React.createElement('div'))).toEqual(true);
expect(React.isValidElement(React.createElement(Component))).toEqual(true);
expect(React.isValidElement(null)).toEqual(false);
expect(React.isValidElement(true)).toEqual(false);
@@ -314,7 +318,7 @@ describe('ReactElement', () => {
expect(React.isValidElement('string')).toEqual(false);
expect(React.isValidElement(React.DOM.div)).toEqual(false);
expect(React.isValidElement(Component)).toEqual(false);
expect(React.isValidElement({ type: 'div', props: {} })).toEqual(false);
expect(React.isValidElement({type: 'div', props: {}})).toEqual(false);
var jsonElement = JSON.stringify(React.createElement('div'));
expect(React.isValidElement(JSON.parse(jsonElement))).toBe(true);
@@ -341,7 +345,7 @@ describe('ReactElement', () => {
var container = document.createElement('div');
var instance = ReactDOM.render(
React.createElement(Component, {fruit: 'mango'}),
container
container,
);
expect(instance.props.fruit).toBe('mango');
@@ -360,12 +364,12 @@ describe('ReactElement', () => {
Component.defaultProps = {prop: 'testKey'};
var instance = ReactTestUtils.renderIntoDocument(
React.createElement(Component)
React.createElement(Component),
);
expect(instance.props.prop).toBe('testKey');
var inst2 = ReactTestUtils.renderIntoDocument(
React.createElement(Component, {prop: null})
React.createElement(Component, {prop: null}),
);
expect(inst2.props.prop).toBe(null);
});
@@ -448,10 +452,8 @@ describe('ReactElement', () => {
}
}
expect(React.isValidElement(React.createElement('div')))
.toEqual(true);
expect(React.isValidElement(React.createElement(Component)))
.toEqual(true);
expect(React.isValidElement(React.createElement('div'))).toEqual(true);
expect(React.isValidElement(React.createElement(Component))).toEqual(true);
expect(React.isValidElement(null)).toEqual(false);
expect(React.isValidElement(true)).toEqual(false);
@@ -459,12 +461,11 @@ describe('ReactElement', () => {
expect(React.isValidElement('string')).toEqual(false);
expect(React.isValidElement(React.DOM.div)).toEqual(false);
expect(React.isValidElement(Component)).toEqual(false);
expect(React.isValidElement({ type: 'div', props: {} })).toEqual(false);
expect(React.isValidElement({type: 'div', props: {}})).toEqual(false);
var jsonElement = JSON.stringify(React.createElement('div'));
expect(React.isValidElement(JSON.parse(jsonElement))).toBe(false);
});
});
describe('comparing jsx vs .createFactory() vs .createElement()', () => {
@@ -478,7 +479,6 @@ describe('comparing jsx vs .createFactory() vs .createElement()', () => {
Child = jest.genMockFromModule('ReactElementTestChild');
});
describe('when using jsx only', () => {
var Parent, instance;
beforeEach(() => {
@@ -491,11 +491,14 @@ describe('comparing jsx vs .createFactory() vs .createElement()', () => {
);
}
};
instance = ReactTestUtils.renderIntoDocument(<Parent/>);
instance = ReactTestUtils.renderIntoDocument(<Parent />);
});
it('should scry children but cannot', () => {
var children = ReactTestUtils.scryRenderedComponentsWithType(instance, Child);
var children = ReactTestUtils.scryRenderedComponentsWithType(
instance,
Child,
);
expect(children.length).toBe(1);
});
@@ -504,7 +507,10 @@ describe('comparing jsx vs .createFactory() vs .createElement()', () => {
});
it('can capture Child instantiation calls', () => {
expect(Child.mock.calls[0][0]).toEqual({ foo: 'foo value', children: 'children value' });
expect(Child.mock.calls[0][0]).toEqual({
foo: 'foo value',
children: 'children value',
});
});
});
@@ -514,7 +520,10 @@ describe('comparing jsx vs .createFactory() vs .createElement()', () => {
var childFactory = React.createFactory(Child);
class Parent extends React.Component {
render() {
return React.DOM.div({}, childFactory({ ref: 'child', foo: 'foo value' }, 'children value'));
return React.DOM.div(
{},
childFactory({ref: 'child', foo: 'foo value'}, 'children value'),
);
}
}
factory = React.createFactory(Parent);
@@ -522,7 +531,10 @@ describe('comparing jsx vs .createFactory() vs .createElement()', () => {
});
it('can properly scry children', () => {
var children = ReactTestUtils.scryRenderedComponentsWithType(instance, Child);
var children = ReactTestUtils.scryRenderedComponentsWithType(
instance,
Child,
);
expect(children.length).toBe(1);
});
@@ -531,7 +543,10 @@ describe('comparing jsx vs .createFactory() vs .createElement()', () => {
});
it('can capture Child instantiation calls', () => {
expect(Child.mock.calls[0][0]).toEqual({ foo: 'foo value', children: 'children value' });
expect(Child.mock.calls[0][0]).toEqual({
foo: 'foo value',
children: 'children value',
});
});
});
@@ -540,7 +555,14 @@ describe('comparing jsx vs .createFactory() vs .createElement()', () => {
beforeEach(() => {
class Parent extends React.Component {
render() {
return React.DOM.div({}, React.createElement(Child, { ref: 'child', foo: 'foo value' }, 'children value'));
return React.DOM.div(
{},
React.createElement(
Child,
{ref: 'child', foo: 'foo value'},
'children value',
),
);
}
}
factory = React.createFactory(Parent);
@@ -548,7 +570,10 @@ describe('comparing jsx vs .createFactory() vs .createElement()', () => {
});
it('should scry children but cannot', () => {
var children = ReactTestUtils.scryRenderedComponentsWithType(instance, Child);
var children = ReactTestUtils.scryRenderedComponentsWithType(
instance,
Child,
);
expect(children.length).toBe(1);
});
@@ -557,8 +582,10 @@ describe('comparing jsx vs .createFactory() vs .createElement()', () => {
});
it('can capture Child instantiation calls', () => {
expect(Child.mock.calls[0][0]).toEqual({ foo: 'foo value', children: 'children value' });
expect(Child.mock.calls[0][0]).toEqual({
foo: 'foo value',
children: 'children value',
});
});
});
});
@@ -42,7 +42,7 @@ describe('ReactElementClone', () => {
render() {
return (
<div className="parent">
{React.cloneElement(this.props.child, { className: 'xyz' })}
{React.cloneElement(this.props.child, {className: 'xyz'})}
</div>
);
}
@@ -66,7 +66,7 @@ describe('ReactElementClone', () => {
render() {
return (
<div className="parent">
{React.cloneElement(this.props.child, { className: 'xyz' })}
{React.cloneElement(this.props.child, {className: 'xyz'})}
</div>
);
}
@@ -91,7 +91,7 @@ describe('ReactElementClone', () => {
render() {
return (
<div>
{React.cloneElement(this.props.child, { className: 'xyz' })}
{React.cloneElement(this.props.child, {className: 'xyz'})}
</div>
);
}
@@ -120,7 +120,7 @@ describe('ReactElementClone', () => {
}
ReactTestUtils.renderIntoDocument(
React.cloneElement(<Component />, {children: 'xyz'})
React.cloneElement(<Component />, {children: 'xyz'}),
);
});
@@ -133,7 +133,7 @@ describe('ReactElementClone', () => {
}
ReactTestUtils.renderIntoDocument(
React.cloneElement(<Component>xyz</Component>, {})
React.cloneElement(<Component>xyz</Component>, {}),
);
});
@@ -146,34 +146,41 @@ describe('ReactElementClone', () => {
var clone = React.cloneElement(
<Component>xyz</Component>,
{ children: <Component /> },
<div />,
<span />
);
expect(clone.props.children).toEqual([
{children: <Component />},
<div />,
<span />,
]);
);
expect(clone.props.children).toEqual([<div />, <span />]);
});
it('should override children if undefined is provided as an argument', () => {
var element = React.createElement(ComponentClass, {
children: 'text',
}, undefined);
var element = React.createElement(
ComponentClass,
{
children: 'text',
},
undefined,
);
expect(element.props.children).toBe(undefined);
var element2 = React.cloneElement(React.createElement(ComponentClass, {
children: 'text',
}), {}, undefined);
var element2 = React.cloneElement(
React.createElement(ComponentClass, {
children: 'text',
}),
{},
undefined,
);
expect(element2.props.children).toBe(undefined);
});
it('should support keys and refs', () => {
class Parent extends React.Component {
render() {
var clone =
React.cloneElement(this.props.children, {key: 'xyz', ref: 'xyz'});
var clone = React.cloneElement(this.props.children, {
key: 'xyz',
ref: 'xyz',
});
expect(clone.key).toBe('xyz');
expect(clone.ref).toBe('xyz');
return <div>{clone}</div>;
@@ -218,7 +225,7 @@ describe('ReactElementClone', () => {
}
ReactTestUtils.renderIntoDocument(
React.cloneElement(<Component myprop="abc" />, {myprop: 'xyz'})
React.cloneElement(<Component myprop="abc" />, {myprop: 'xyz'}),
);
});
@@ -250,7 +257,7 @@ describe('ReactElementClone', () => {
expect(console.error.calls.count()).toBe(1);
expect(console.error.calls.argsFor(0)[0]).toContain(
'Each child in an array or iterator should have a unique "key" prop.'
'Each child in an array or iterator should have a unique "key" prop.',
);
});
@@ -295,21 +302,20 @@ describe('ReactElementClone', () => {
}
class GrandParent extends React.Component {
render() {
return React.createElement(
Parent,
{ child: React.createElement(Component, {color: 'red'}) }
);
return React.createElement(Parent, {
child: React.createElement(Component, {color: 'red'}),
});
}
}
ReactTestUtils.renderIntoDocument(React.createElement(GrandParent));
expect(console.error.calls.count()).toBe(1);
expect(console.error.calls.argsFor(0)[0]).toBe(
'Warning: Failed prop type: ' +
'Invalid prop `color` of type `number` supplied to `Component`, ' +
'expected `string`.\n' +
' in Component (created by GrandParent)\n' +
' in Parent (created by GrandParent)\n' +
' in GrandParent'
'Invalid prop `color` of type `number` supplied to `Component`, ' +
'expected `string`.\n' +
' in Component (created by GrandParent)\n' +
' in Parent (created by GrandParent)\n' +
' in GrandParent',
);
});
@@ -359,5 +365,4 @@ describe('ReactElementClone', () => {
expect(Object.isFrozen(element.props)).toBe(true);
expect(clone.props).toEqual({foo: 'ef'});
});
});
@@ -46,7 +46,7 @@ describe('ReactElementValidator', () => {
expect(console.error.calls.count()).toBe(1);
expect(console.error.calls.argsFor(0)[0]).toContain(
'Each child in an array or iterator should have a unique "key" prop.'
'Each child in an array or iterator should have a unique "key" prop.',
);
});
@@ -64,19 +64,17 @@ describe('ReactElementValidator', () => {
class ComponentWrapper extends React.Component {
render() {
return InnerComponent({childSet: [Component(), Component()] });
return InnerComponent({childSet: [Component(), Component()]});
}
}
ReactTestUtils.renderIntoDocument(
React.createElement(ComponentWrapper)
);
ReactTestUtils.renderIntoDocument(React.createElement(ComponentWrapper));
expect(console.error.calls.count()).toBe(1);
expect(console.error.calls.argsFor(0)[0]).toContain(
'Each child in an array or iterator should have a unique "key" prop. ' +
'Check the render method of `InnerClass`. ' +
'It was passed a child from ComponentWrapper. '
'Check the render method of `InnerClass`. ' +
'It was passed a child from ComponentWrapper. ',
);
});
@@ -86,37 +84,31 @@ describe('ReactElementValidator', () => {
function Anonymous() {
return <div />;
}
Object.defineProperty(Anonymous, 'name', { value: undefined });
Object.defineProperty(Anonymous, 'name', {value: undefined});
var divs = [
<div />,
<div />,
];
var divs = [<div />, <div />];
ReactTestUtils.renderIntoDocument(<Anonymous>{divs}</Anonymous>);
expect(console.error.calls.count()).toBe(1);
expect(normalizeCodeLocInfo(console.error.calls.argsFor(0)[0])).toBe(
'Warning: Each child in an array or iterator should have a unique ' +
'"key" prop. See https://fb.me/react-warning-keys for more information.\n' +
' in div (at **)'
'"key" prop. See https://fb.me/react-warning-keys for more information.\n' +
' in div (at **)',
);
});
it('warns for keys for arrays of elements with no owner info', () => {
spyOn(console, 'error');
var divs = [
<div />,
<div />,
];
var divs = [<div />, <div />];
ReactTestUtils.renderIntoDocument(<div>{divs}</div>);
expect(console.error.calls.count()).toBe(1);
expect(normalizeCodeLocInfo(console.error.calls.argsFor(0)[0])).toBe(
'Warning: Each child in an array or iterator should have a unique ' +
'"key" prop. Check the top-level render call using <div>. See ' +
'https://fb.me/react-warning-keys for more information.\n' +
' in div (at **)'
'"key" prop. Check the top-level render call using <div>. See ' +
'https://fb.me/react-warning-keys for more information.\n' +
' in div (at **)',
);
});
@@ -140,12 +132,12 @@ describe('ReactElementValidator', () => {
expect(console.error.calls.count()).toBe(1);
expect(normalizeCodeLocInfo(console.error.calls.argsFor(0)[0])).toBe(
'Warning: Each child in an array or iterator should have a unique ' +
'"key" prop. Check the render method of `Component`. See ' +
'https://fb.me/react-warning-keys for more information.\n' +
' in div (at **)\n' +
' in Component (at **)\n' +
' in Parent (at **)\n' +
' in GrandParent (at **)'
'"key" prop. Check the render method of `Component`. See ' +
'https://fb.me/react-warning-keys for more information.\n' +
' in div (at **)\n' +
' in Component (at **)\n' +
' in Parent (at **)\n' +
' in GrandParent (at **)',
);
});
@@ -165,7 +157,7 @@ describe('ReactElementValidator', () => {
<Wrapper>
<span />
<span />
</Wrapper>
</Wrapper>,
);
expect(console.error.calls.count()).toBe(0);
@@ -191,7 +183,7 @@ describe('ReactElementValidator', () => {
expect(console.error.calls.count()).toBe(1);
expect(console.error.calls.argsFor(0)[0]).toContain(
'Each child in an array or iterator should have a unique "key" prop.'
'Each child in an array or iterator should have a unique "key" prop.',
);
});
@@ -266,10 +258,10 @@ describe('ReactElementValidator', () => {
ReactTestUtils.renderIntoDocument(React.createElement(ParentComp));
expect(console.error.calls.argsFor(0)[0]).toBe(
'Warning: Failed prop type: ' +
'Invalid prop `color` of type `number` supplied to `MyComp`, ' +
'expected `string`.\n' +
' in MyComp (created by ParentComp)\n' +
' in ParentComp'
'Invalid prop `color` of type `number` supplied to `MyComp`, ' +
'expected `string`.\n' +
' in MyComp (created by ParentComp)\n' +
' in ParentComp',
);
});
@@ -284,35 +276,35 @@ describe('ReactElementValidator', () => {
expect(console.error.calls.count()).toBe(6);
expect(console.error.calls.argsFor(0)[0]).toBe(
'Warning: React.createElement: type is invalid -- expected a string ' +
'(for built-in components) or a class/function (for composite ' +
'components) but got: undefined. You likely forgot to export your ' +
'component from the file it\'s defined in.'
'(for built-in components) or a class/function (for composite ' +
'components) but got: undefined. You likely forgot to export your ' +
"component from the file it's defined in.",
);
expect(console.error.calls.argsFor(1)[0]).toBe(
'Warning: React.createElement: type is invalid -- expected a string ' +
'(for built-in components) or a class/function (for composite ' +
'components) but got: null.'
'(for built-in components) or a class/function (for composite ' +
'components) but got: null.',
);
expect(console.error.calls.argsFor(2)[0]).toBe(
'Warning: React.createElement: type is invalid -- expected a string ' +
'(for built-in components) or a class/function (for composite ' +
'components) but got: boolean.'
'(for built-in components) or a class/function (for composite ' +
'components) but got: boolean.',
);
expect(console.error.calls.argsFor(3)[0]).toBe(
'Warning: React.createElement: type is invalid -- expected a string ' +
'(for built-in components) or a class/function (for composite ' +
'components) but got: number.'
'(for built-in components) or a class/function (for composite ' +
'components) but got: number.',
);
expect(console.error.calls.argsFor(4)[0]).toBe(
'Warning: React.createElement: type is invalid -- expected a string ' +
'(for built-in components) or a class/function (for composite ' +
'components) but got: object.'
'(for built-in components) or a class/function (for composite ' +
'components) but got: object.',
);
expect(console.error.calls.argsFor(5)[0]).toBe(
'Warning: React.createElement: type is invalid -- expected a string ' +
'(for built-in components) or a class/function (for composite ' +
'components) but got: object. You likely forgot to export your ' +
'component from the file it\'s defined in.'
'(for built-in components) or a class/function (for composite ' +
'components) but got: object. You likely forgot to export your ' +
"component from the file it's defined in.",
);
React.createElement('div');
expect(console.error.calls.count()).toBe(6);
@@ -327,15 +319,15 @@ describe('ReactElementValidator', () => {
ReactTestUtils.renderIntoDocument(React.createElement(ParentComp));
}).toThrowError(
'Element type is invalid: expected a string (for built-in components) ' +
'or a class/function (for composite components) but got: null. Check ' +
'the render method of `ParentComp`.'
'or a class/function (for composite components) but got: null. Check ' +
'the render method of `ParentComp`.',
);
expect(console.error.calls.count()).toBe(1);
expect(console.error.calls.argsFor(0)[0]).toBe(
'Warning: React.createElement: type is invalid -- expected a string ' +
'(for built-in components) or a class/function (for composite ' +
'components) but got: null. Check the render method of `ParentComp`.' +
'\n in ParentComp'
'(for built-in components) or a class/function (for composite ' +
'components) but got: null. Check the render method of `ParentComp`.' +
'\n in ParentComp',
);
});
@@ -355,8 +347,8 @@ describe('ReactElementValidator', () => {
expect(console.error.calls.count()).toBe(1);
expect(console.error.calls.argsFor(0)[0]).toBe(
'Warning: Failed prop type: The prop `prop` is marked as required in ' +
'`Component`, but its value is `null`.\n' +
' in Component'
'`Component`, but its value is `null`.\n' +
' in Component',
);
});
@@ -372,14 +364,14 @@ describe('ReactElementValidator', () => {
Component.defaultProps = {prop: 'text'};
ReactTestUtils.renderIntoDocument(
React.createElement(Component, {prop:null})
React.createElement(Component, {prop: null}),
);
expect(console.error.calls.count()).toBe(1);
expect(console.error.calls.argsFor(0)[0]).toBe(
'Warning: Failed prop type: The prop `prop` is marked as required in ' +
'`Component`, but its value is `null`.\n' +
' in Component'
'`Component`, but its value is `null`.\n' +
' in Component',
);
});
@@ -395,30 +387,28 @@ describe('ReactElementValidator', () => {
prop: React.PropTypes.string.isRequired,
};
ReactTestUtils.renderIntoDocument(React.createElement(Component));
ReactTestUtils.renderIntoDocument(
React.createElement(Component)
);
ReactTestUtils.renderIntoDocument(
React.createElement(Component, {prop: 42})
React.createElement(Component, {prop: 42}),
);
expect(console.error.calls.count()).toBe(2);
expect(console.error.calls.argsFor(0)[0]).toBe(
'Warning: Failed prop type: ' +
'The prop `prop` is marked as required in `Component`, but its value ' +
'is `undefined`.\n' +
' in Component'
'The prop `prop` is marked as required in `Component`, but its value ' +
'is `undefined`.\n' +
' in Component',
);
expect(console.error.calls.argsFor(1)[0]).toBe(
'Warning: Failed prop type: ' +
'Invalid prop `prop` of type `number` supplied to ' +
'`Component`, expected `string`.\n' +
' in Component'
'Invalid prop `prop` of type `number` supplied to ' +
'`Component`, expected `string`.\n' +
' in Component',
);
ReactTestUtils.renderIntoDocument(
React.createElement(Component, {prop: 'string'})
React.createElement(Component, {prop: 'string'}),
);
// Should not error for strings
@@ -431,7 +421,6 @@ describe('ReactElementValidator', () => {
class Component extends React.Component {
render() {
return React.createElement('span', null, this.props.myProp.value);
}
}
Component.propTypes = {
@@ -439,16 +428,16 @@ describe('ReactElementValidator', () => {
};
ReactTestUtils.renderIntoDocument(
React.createElement(Component, {myProp: {value: 'hi'}})
React.createElement(Component, {myProp: {value: 'hi'}}),
);
expect(console.error.calls.count()).toBe(1);
expect(console.error.calls.argsFor(0)[0]).toBe(
'Warning: Component: type specification of prop `myProp` is invalid; ' +
'the type checker function must return `null` or an `Error` but ' +
'returned a function. You may have forgotten to pass an argument to ' +
'the type checker creator (arrayOf, instanceOf, objectOf, oneOf, ' +
'oneOfType, and shape all require an argument).'
'the type checker function must return `null` or an `Error` but ' +
'returned a function. You may have forgotten to pass an argument to ' +
'the type checker creator (arrayOf, instanceOf, objectOf, oneOf, ' +
'oneOfType, and shape all require an argument).',
);
});
@@ -462,7 +451,7 @@ describe('ReactElementValidator', () => {
expect(console.error.calls.count()).toBe(1);
expect(console.error.calls.argsFor(0)[0]).toBe(
'Warning: Factory.type is deprecated. Access the class directly before ' +
'passing it to createFactory.'
'passing it to createFactory.',
);
// Warn once, not again
expect(TestFactory.type).toBe(TestComponent);
@@ -511,7 +500,7 @@ describe('ReactElementValidator', () => {
// shouldn't blow up either.
var child = {
$$typeof: (<div />).$$typeof,
$$typeof: <div />.$$typeof,
type: 'span',
key: null,
ref: null,
@@ -529,10 +518,9 @@ describe('ReactElementValidator', () => {
expect(console.error.calls.count()).toBe(1);
expect(normalizeCodeLocInfo(console.error.calls.argsFor(0)[0])).toBe(
'Warning: React.createElement: type is invalid -- expected a string ' +
'(for built-in components) or a class/function (for composite ' +
'components) but got: undefined. You likely forgot to export your ' +
'component from the file it\'s defined in. Check your code at **.'
'(for built-in components) or a class/function (for composite ' +
'components) but got: undefined. You likely forgot to export your ' +
"component from the file it's defined in. Check your code at **.",
);
});
});
@@ -28,16 +28,18 @@ function typeCheckFail(declaration, value, message) {
'testComponent',
'prop',
null,
ReactPropTypesSecret
ReactPropTypesSecret,
);
expect(error instanceof Error).toBe(true);
expect(error.message).toBe(message);
}
function typeCheckFailRequiredValues(declaration) {
var specifiedButIsNullMsg = 'The prop `testProp` is marked as required in ' +
var specifiedButIsNullMsg =
'The prop `testProp` is marked as required in ' +
'`testComponent`, but its value is `null`.';
var unspecifiedMsg = 'The prop `testProp` is marked as required in ' +
var unspecifiedMsg =
'The prop `testProp` is marked as required in ' +
'`testComponent`, but its value is \`undefined\`.';
var props1 = {testProp: null};
var error1 = declaration(
@@ -46,7 +48,7 @@ function typeCheckFailRequiredValues(declaration) {
'testComponent',
'prop',
null,
ReactPropTypesSecret
ReactPropTypesSecret,
);
expect(error1 instanceof Error).toBe(true);
expect(error1.message).toBe(specifiedButIsNullMsg);
@@ -57,7 +59,7 @@ function typeCheckFailRequiredValues(declaration) {
'testComponent',
'prop',
null,
ReactPropTypesSecret
ReactPropTypesSecret,
);
expect(error2 instanceof Error).toBe(true);
expect(error2.message).toBe(unspecifiedMsg);
@@ -68,7 +70,7 @@ function typeCheckFailRequiredValues(declaration) {
'testComponent',
'prop',
null,
ReactPropTypesSecret
ReactPropTypesSecret,
);
expect(error3 instanceof Error).toBe(true);
expect(error3.message).toBe(unspecifiedMsg);
@@ -82,7 +84,7 @@ function typeCheckPass(declaration, value) {
'testComponent',
'prop',
null,
ReactPropTypesSecret
ReactPropTypesSecret,
);
expect(error).toBe(null);
}
@@ -92,16 +94,11 @@ function expectWarningInDevelopment(declaration, value) {
var propName = 'testProp' + Math.random().toString();
var componentName = 'testComponent' + Math.random().toString();
for (var i = 0; i < 3; i++) {
declaration(
props,
propName,
componentName,
'prop'
);
declaration(props, propName, componentName, 'prop');
}
expect(console.error.calls.count()).toBe(1);
expect(console.error.calls.argsFor(0)[0]).toContain(
'You are manually calling a React.PropTypes validation '
'You are manually calling a React.PropTypes validation ',
);
console.error.calls.reset();
}
@@ -121,31 +118,31 @@ describe('ReactPropTypes', () => {
PropTypes.string,
[],
'Invalid prop `testProp` of type `array` supplied to ' +
'`testComponent`, expected `string`.'
'`testComponent`, expected `string`.',
);
typeCheckFail(
PropTypes.string,
false,
'Invalid prop `testProp` of type `boolean` supplied to ' +
'`testComponent`, expected `string`.'
'`testComponent`, expected `string`.',
);
typeCheckFail(
PropTypes.string,
0,
'Invalid prop `testProp` of type `number` supplied to ' +
'`testComponent`, expected `string`.'
'`testComponent`, expected `string`.',
);
typeCheckFail(
PropTypes.string,
{},
'Invalid prop `testProp` of type `object` supplied to ' +
'`testComponent`, expected `string`.'
'`testComponent`, expected `string`.',
);
typeCheckFail(
PropTypes.string,
Symbol(),
'Invalid prop `testProp` of type `symbol` supplied to ' +
'`testComponent`, expected `string`.'
'`testComponent`, expected `string`.',
);
});
@@ -154,13 +151,13 @@ describe('ReactPropTypes', () => {
PropTypes.string,
new Date(),
'Invalid prop `testProp` of type `date` supplied to ' +
'`testComponent`, expected `string`.'
'`testComponent`, expected `string`.',
);
typeCheckFail(
PropTypes.string,
/please/,
'Invalid prop `testProp` of type `regexp` supplied to ' +
'`testComponent`, expected `string`.'
'`testComponent`, expected `string`.',
);
});
@@ -260,9 +257,9 @@ describe('ReactPropTypes', () => {
describe('ArrayOf Type', () => {
it('should fail for invalid argument', () => {
typeCheckFail(
PropTypes.arrayOf({ foo: PropTypes.string }),
{ foo: 'bar' },
'Property `testProp` of component `testComponent` has invalid PropType notation inside arrayOf.'
PropTypes.arrayOf({foo: PropTypes.string}),
{foo: 'bar'},
'Property `testProp` of component `testComponent` has invalid PropType notation inside arrayOf.',
);
});
@@ -276,14 +273,14 @@ describe('ReactPropTypes', () => {
it('should support arrayOf with complex types', () => {
typeCheckPass(
PropTypes.arrayOf(PropTypes.shape({a: PropTypes.number.isRequired})),
[{a: 1}, {a: 2}]
[{a: 1}, {a: 2}],
);
function Thing() {}
typeCheckPass(
PropTypes.arrayOf(PropTypes.instanceOf(Thing)),
[new Thing(), new Thing()]
);
typeCheckPass(PropTypes.arrayOf(PropTypes.instanceOf(Thing)), [
new Thing(),
new Thing(),
]);
});
it('should warn with invalid items in the array', () => {
@@ -291,7 +288,7 @@ describe('ReactPropTypes', () => {
PropTypes.arrayOf(PropTypes.number),
[1, 2, 'b'],
'Invalid prop `testProp[2]` of type `string` supplied to ' +
'`testComponent`, expected `number`.'
'`testComponent`, expected `number`.',
);
});
@@ -303,7 +300,9 @@ describe('ReactPropTypes', () => {
PropTypes.arrayOf(PropTypes.instanceOf(Thing)),
[new Thing(), 'xyz'],
'Invalid prop `testProp[1]` of type `String` supplied to ' +
'`testComponent`, expected instance of `' + name + '`.'
'`testComponent`, expected instance of `' +
name +
'`.',
);
});
@@ -312,19 +311,19 @@ describe('ReactPropTypes', () => {
PropTypes.arrayOf(PropTypes.number),
{'0': 'maybe-array', length: 1},
'Invalid prop `testProp` of type `object` supplied to ' +
'`testComponent`, expected an array.'
'`testComponent`, expected an array.',
);
typeCheckFail(
PropTypes.arrayOf(PropTypes.number),
123,
'Invalid prop `testProp` of type `number` supplied to ' +
'`testComponent`, expected an array.'
'`testComponent`, expected an array.',
);
typeCheckFail(
PropTypes.arrayOf(PropTypes.number),
'string',
'Invalid prop `testProp` of type `string` supplied to ' +
'`testComponent`, expected an array.'
'`testComponent`, expected an array.',
);
});
@@ -339,26 +338,32 @@ describe('ReactPropTypes', () => {
it('should warn for missing required values', () => {
typeCheckFailRequiredValues(
PropTypes.arrayOf(PropTypes.number).isRequired
PropTypes.arrayOf(PropTypes.number).isRequired,
);
});
it('should warn if called manually in development', () => {
spyOn(console, 'error');
expectWarningInDevelopment(PropTypes.arrayOf({foo: PropTypes.string}), {
foo: 'bar',
});
expectWarningInDevelopment(PropTypes.arrayOf(PropTypes.number), [
1,
2,
'b',
]);
expectWarningInDevelopment(PropTypes.arrayOf(PropTypes.number), {
'0': 'maybe-array',
length: 1,
});
expectWarningInDevelopment(
PropTypes.arrayOf({ foo: PropTypes.string }),
{ foo: 'bar' }
PropTypes.arrayOf(PropTypes.number).isRequired,
null,
);
expectWarningInDevelopment(
PropTypes.arrayOf(PropTypes.number),
[1, 2, 'b']
PropTypes.arrayOf(PropTypes.number).isRequired,
undefined,
);
expectWarningInDevelopment(
PropTypes.arrayOf(PropTypes.number),
{'0': 'maybe-array', length: 1}
);
expectWarningInDevelopment(PropTypes.arrayOf(PropTypes.number).isRequired, null);
expectWarningInDevelopment(PropTypes.arrayOf(PropTypes.number).isRequired, undefined);
});
});
@@ -384,25 +389,25 @@ describe('ReactPropTypes', () => {
PropTypes.element,
[<div />, <div />],
'Invalid prop `testProp` of type `array` supplied to `testComponent`, ' +
'expected a single ReactElement.'
'expected a single ReactElement.',
);
typeCheckFail(
PropTypes.element,
123,
'Invalid prop `testProp` of type `number` supplied to `testComponent`, ' +
'expected a single ReactElement.'
'expected a single ReactElement.',
);
typeCheckFail(
PropTypes.element,
'foo',
'Invalid prop `testProp` of type `string` supplied to `testComponent`, ' +
'expected a single ReactElement.'
'expected a single ReactElement.',
);
typeCheckFail(
PropTypes.element,
false,
'Invalid prop `testProp` of type `boolean` supplied to `testComponent`, ' +
'expected a single ReactElement.'
'expected a single ReactElement.',
);
});
@@ -443,7 +448,6 @@ describe('ReactPropTypes', () => {
expectWarningInDevelopment(PropTypes.element.isRequired, null);
expectWarningInDevelopment(PropTypes.element.isRequired, undefined);
});
});
describe('Instance Types', () => {
@@ -458,43 +462,57 @@ describe('ReactPropTypes', () => {
PropTypes.instanceOf(Person),
false,
'Invalid prop `testProp` of type `Boolean` supplied to ' +
'`testComponent`, expected instance of `' + personName + '`.'
'`testComponent`, expected instance of `' +
personName +
'`.',
);
typeCheckFail(
PropTypes.instanceOf(Person),
{},
'Invalid prop `testProp` of type `Object` supplied to ' +
'`testComponent`, expected instance of `' + personName + '`.'
'`testComponent`, expected instance of `' +
personName +
'`.',
);
typeCheckFail(
PropTypes.instanceOf(Person),
'',
'Invalid prop `testProp` of type `String` supplied to ' +
'`testComponent`, expected instance of `' + personName + '`.'
'`testComponent`, expected instance of `' +
personName +
'`.',
);
typeCheckFail(
PropTypes.instanceOf(Date),
{},
'Invalid prop `testProp` of type `Object` supplied to ' +
'`testComponent`, expected instance of `' + dateName + '`.'
'`testComponent`, expected instance of `' +
dateName +
'`.',
);
typeCheckFail(
PropTypes.instanceOf(RegExp),
{},
'Invalid prop `testProp` of type `Object` supplied to ' +
'`testComponent`, expected instance of `' + regExpName + '`.'
'`testComponent`, expected instance of `' +
regExpName +
'`.',
);
typeCheckFail(
PropTypes.instanceOf(Person),
new Cat(),
'Invalid prop `testProp` of type `Cat` supplied to ' +
'`testComponent`, expected instance of `' + personName + '`.'
'`testComponent`, expected instance of `' +
personName +
'`.',
);
typeCheckFail(
PropTypes.instanceOf(Person),
Object.create(null),
'Invalid prop `testProp` of type `<<anonymous>>` supplied to ' +
'`testComponent`, expected instance of `' + personName + '`.'
'`testComponent`, expected instance of `' +
personName +
'`.',
);
});
@@ -524,9 +542,11 @@ describe('ReactPropTypes', () => {
expectWarningInDevelopment(PropTypes.instanceOf(Date), {});
expectWarningInDevelopment(PropTypes.instanceOf(Date), new Date());
expectWarningInDevelopment(PropTypes.instanceOf(Date).isRequired, {});
expectWarningInDevelopment(PropTypes.instanceOf(Date).isRequired, new Date());
expectWarningInDevelopment(
PropTypes.instanceOf(Date).isRequired,
new Date(),
);
});
});
describe('React Component Types', () => {
@@ -539,7 +559,8 @@ describe('ReactPropTypes', () => {
});
it('should warn for invalid values', () => {
var failMessage = 'Invalid prop `testProp` supplied to ' +
var failMessage =
'Invalid prop `testProp` supplied to ' +
'`testComponent`, expected a ReactNode.';
typeCheckFail(PropTypes.node, true, failMessage);
typeCheckFail(PropTypes.node, function() {}, failMessage);
@@ -565,18 +586,21 @@ describe('ReactPropTypes', () => {
// Object of renderable things
var frag = ReactFragment.create;
typeCheckPass(PropTypes.node, frag({
k0: 123,
k1: 'Some string',
k2: <div />,
k3: frag({
k30: <MyComponent />,
k31: frag({k310: <a />}),
k32: 'Another string',
typeCheckPass(
PropTypes.node,
frag({
k0: 123,
k1: 'Some string',
k2: <div />,
k3: frag({
k30: <MyComponent />,
k31: frag({k310: <a />}),
k32: 'Another string',
}),
k4: null,
k5: undefined,
}),
k4: null,
k5: undefined,
}));
);
expect(console.error.calls.count()).toBe(0);
});
@@ -603,7 +627,10 @@ describe('ReactPropTypes', () => {
return {
next: function() {
var done = ++i > 2;
return {value: done ? undefined : ['#' + i, <MyComponent />], done: done};
return {
value: done ? undefined : ['#' + i, <MyComponent />],
done: done,
};
},
};
},
@@ -634,45 +661,46 @@ describe('ReactPropTypes', () => {
expectWarningInDevelopment(PropTypes.node.isRequired, undefined);
expectWarningInDevelopment(PropTypes.node.isRequired, undefined);
});
});
describe('ObjectOf Type', () => {
it('should fail for invalid argument', () => {
typeCheckFail(
PropTypes.objectOf({ foo: PropTypes.string }),
{ foo: 'bar' },
'Property `testProp` of component `testComponent` has invalid PropType notation inside objectOf.'
PropTypes.objectOf({foo: PropTypes.string}),
{foo: 'bar'},
'Property `testProp` of component `testComponent` has invalid PropType notation inside objectOf.',
);
});
it('should support the objectOf propTypes', () => {
typeCheckPass(PropTypes.objectOf(PropTypes.number), {a: 1, b: 2, c: 3});
typeCheckPass(
PropTypes.objectOf(PropTypes.string),
{a: 'a', b: 'b', c: 'c'}
);
typeCheckPass(
PropTypes.objectOf(PropTypes.oneOf(['a', 'b'])),
{a: 'a', b: 'b'}
);
typeCheckPass(
PropTypes.objectOf(PropTypes.symbol),
{a: Symbol(), b: Symbol(), c: Symbol()}
);
typeCheckPass(PropTypes.objectOf(PropTypes.string), {
a: 'a',
b: 'b',
c: 'c',
});
typeCheckPass(PropTypes.objectOf(PropTypes.oneOf(['a', 'b'])), {
a: 'a',
b: 'b',
});
typeCheckPass(PropTypes.objectOf(PropTypes.symbol), {
a: Symbol(),
b: Symbol(),
c: Symbol(),
});
});
it('should support objectOf with complex types', () => {
typeCheckPass(
PropTypes.objectOf(PropTypes.shape({a: PropTypes.number.isRequired})),
{a: {a: 1}, b: {a: 2}}
{a: {a: 1}, b: {a: 2}},
);
function Thing() {}
typeCheckPass(
PropTypes.objectOf(PropTypes.instanceOf(Thing)),
{a: new Thing(), b: new Thing()}
);
typeCheckPass(PropTypes.objectOf(PropTypes.instanceOf(Thing)), {
a: new Thing(),
b: new Thing(),
});
});
it('should warn with invalid items in the object', () => {
@@ -680,7 +708,7 @@ describe('ReactPropTypes', () => {
PropTypes.objectOf(PropTypes.number),
{a: 1, b: 2, c: 'b'},
'Invalid prop `testProp.c` of type `string` supplied to `testComponent`, ' +
'expected `number`.'
'expected `number`.',
);
});
@@ -692,7 +720,9 @@ describe('ReactPropTypes', () => {
PropTypes.objectOf(PropTypes.instanceOf(Thing)),
{a: new Thing(), b: 'xyz'},
'Invalid prop `testProp.b` of type `String` supplied to ' +
'`testComponent`, expected instance of `' + name + '`.'
'`testComponent`, expected instance of `' +
name +
'`.',
);
});
@@ -701,25 +731,25 @@ describe('ReactPropTypes', () => {
PropTypes.objectOf(PropTypes.number),
[1, 2],
'Invalid prop `testProp` of type `array` supplied to ' +
'`testComponent`, expected an object.'
'`testComponent`, expected an object.',
);
typeCheckFail(
PropTypes.objectOf(PropTypes.number),
123,
'Invalid prop `testProp` of type `number` supplied to ' +
'`testComponent`, expected an object.'
'`testComponent`, expected an object.',
);
typeCheckFail(
PropTypes.objectOf(PropTypes.number),
'string',
'Invalid prop `testProp` of type `string` supplied to ' +
'`testComponent`, expected an object.'
'`testComponent`, expected an object.',
);
typeCheckFail(
PropTypes.objectOf(PropTypes.symbol),
Symbol(),
'Invalid prop `testProp` of type `symbol` supplied to ' +
'`testComponent`, expected an object.'
'`testComponent`, expected an object.',
);
});
@@ -734,23 +764,26 @@ describe('ReactPropTypes', () => {
it('should warn for missing required values', () => {
typeCheckFailRequiredValues(
PropTypes.objectOf(PropTypes.number).isRequired
PropTypes.objectOf(PropTypes.number).isRequired,
);
});
it('should warn if called manually in development', () => {
spyOn(console, 'error');
expectWarningInDevelopment(
PropTypes.objectOf({ foo: PropTypes.string }),
{ foo: 'bar' }
);
expectWarningInDevelopment(
PropTypes.objectOf(PropTypes.number),
{a: 1, b: 2, c: 'b'}
);
expectWarningInDevelopment(PropTypes.objectOf({foo: PropTypes.string}), {
foo: 'bar',
});
expectWarningInDevelopment(PropTypes.objectOf(PropTypes.number), {
a: 1,
b: 2,
c: 'b',
});
expectWarningInDevelopment(PropTypes.objectOf(PropTypes.number), [1, 2]);
expectWarningInDevelopment(PropTypes.objectOf(PropTypes.number), null);
expectWarningInDevelopment(PropTypes.objectOf(PropTypes.number), undefined);
expectWarningInDevelopment(
PropTypes.objectOf(PropTypes.number),
undefined,
);
});
});
@@ -761,8 +794,9 @@ describe('ReactPropTypes', () => {
PropTypes.oneOf('red', 'blue');
expect(console.error).toHaveBeenCalled();
expect(console.error.calls.argsFor(0)[0])
.toContain('Invalid argument supplied to oneOf, expected an instance of array.');
expect(console.error.calls.argsFor(0)[0]).toContain(
'Invalid argument supplied to oneOf, expected an instance of array.',
);
typeCheckPass(PropTypes.oneOf('red', 'blue'), 'red');
});
@@ -772,25 +806,25 @@ describe('ReactPropTypes', () => {
PropTypes.oneOf(['red', 'blue']),
true,
'Invalid prop `testProp` of value `true` supplied to ' +
'`testComponent`, expected one of ["red","blue"].'
'`testComponent`, expected one of ["red","blue"].',
);
typeCheckFail(
PropTypes.oneOf(['red', 'blue']),
[],
'Invalid prop `testProp` of value `` supplied to `testComponent`, ' +
'expected one of ["red","blue"].'
'expected one of ["red","blue"].',
);
typeCheckFail(
PropTypes.oneOf(['red', 'blue']),
'',
'Invalid prop `testProp` of value `` supplied to `testComponent`, ' +
'expected one of ["red","blue"].'
'expected one of ["red","blue"].',
);
typeCheckFail(
PropTypes.oneOf([0, 'false']),
false,
'Invalid prop `testProp` of value `false` supplied to ' +
'`testComponent`, expected one of [0,"false"].'
'`testComponent`, expected one of [0,"false"].',
);
});
@@ -824,8 +858,9 @@ describe('ReactPropTypes', () => {
PropTypes.oneOfType(PropTypes.string, PropTypes.number);
expect(console.error).toHaveBeenCalled();
expect(console.error.calls.argsFor(0)[0])
.toContain('Invalid argument supplied to oneOfType, expected an instance of array.');
expect(console.error.calls.argsFor(0)[0]).toContain(
'Invalid argument supplied to oneOfType, expected an instance of array.',
);
typeCheckPass(PropTypes.oneOf(PropTypes.string, PropTypes.number), []);
});
@@ -834,7 +869,7 @@ describe('ReactPropTypes', () => {
typeCheckFail(
PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
[],
'Invalid prop `testProp` supplied to `testComponent`.'
'Invalid prop `testProp` supplied to `testComponent`.',
);
var checker = PropTypes.oneOfType([
@@ -844,15 +879,12 @@ describe('ReactPropTypes', () => {
typeCheckFail(
checker,
{c: 1},
'Invalid prop `testProp` supplied to `testComponent`.'
'Invalid prop `testProp` supplied to `testComponent`.',
);
});
it('should not warn if one of the types are valid', () => {
var checker = PropTypes.oneOfType([
PropTypes.string,
PropTypes.number,
]);
var checker = PropTypes.oneOfType([PropTypes.string, PropTypes.number]);
typeCheckPass(checker, null);
typeCheckPass(checker, 'foo');
typeCheckPass(checker, 123);
@@ -867,16 +899,18 @@ describe('ReactPropTypes', () => {
it('should be implicitly optional and not warn without values', () => {
typeCheckPass(
PropTypes.oneOfType([PropTypes.string, PropTypes.number]), null
PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
null,
);
typeCheckPass(
PropTypes.oneOfType([PropTypes.string, PropTypes.number]), undefined
PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
undefined,
);
});
it('should warn for missing required values', () => {
typeCheckFailRequiredValues(
PropTypes.oneOfType([PropTypes.string, PropTypes.number]).isRequired
PropTypes.oneOfType([PropTypes.string, PropTypes.number]).isRequired,
);
});
@@ -884,18 +918,17 @@ describe('ReactPropTypes', () => {
spyOn(console, 'error');
expectWarningInDevelopment(
PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
[]
[],
);
expectWarningInDevelopment(
PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
null
null,
);
expectWarningInDevelopment(
PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
undefined
undefined,
);
});
});
describe('Shape Types', () => {
@@ -904,13 +937,13 @@ describe('ReactPropTypes', () => {
PropTypes.shape({}),
'some string',
'Invalid prop `testProp` of type `string` supplied to ' +
'`testComponent`, expected `object`.'
'`testComponent`, expected `object`.',
);
typeCheckFail(
PropTypes.shape({}),
['array'],
'Invalid prop `testProp` of type `array` supplied to ' +
'`testComponent`, expected `object`.'
'`testComponent`, expected `object`.',
);
});
@@ -937,7 +970,7 @@ describe('ReactPropTypes', () => {
PropTypes.shape({key: PropTypes.number.isRequired}),
{},
'The prop `testProp.key` is marked as required in `testComponent`, ' +
'but its value is `undefined`.'
'but its value is `undefined`.',
);
});
@@ -949,44 +982,49 @@ describe('ReactPropTypes', () => {
}),
{},
'The prop `testProp.key` is marked as required in `testComponent`, ' +
'but its value is `undefined`.'
'but its value is `undefined`.',
);
});
it('should warn for invalid key types', () => {
typeCheckFail(PropTypes.shape({key: PropTypes.number}),
typeCheckFail(
PropTypes.shape({key: PropTypes.number}),
{key: 'abc'},
'Invalid prop `testProp.key` of type `string` supplied to `testComponent`, ' +
'expected `number`.'
'expected `number`.',
);
});
it('should be implicitly optional and not warn without values', () => {
typeCheckPass(
PropTypes.shape(PropTypes.shape({key: PropTypes.number})), null
PropTypes.shape(PropTypes.shape({key: PropTypes.number})),
null,
);
typeCheckPass(
PropTypes.shape(PropTypes.shape({key: PropTypes.number})), undefined
PropTypes.shape(PropTypes.shape({key: PropTypes.number})),
undefined,
);
});
it('should warn for missing required values', () => {
typeCheckFailRequiredValues(
PropTypes.shape({key: PropTypes.number}).isRequired
PropTypes.shape({key: PropTypes.number}).isRequired,
);
});
it('should warn if called manually in development', () => {
spyOn(console, 'error');
expectWarningInDevelopment(PropTypes.shape({}), 'some string');
expectWarningInDevelopment(PropTypes.shape({ foo: PropTypes.number }), { foo: 42 });
expectWarningInDevelopment(PropTypes.shape({foo: PropTypes.number}), {
foo: 42,
});
expectWarningInDevelopment(
PropTypes.shape({key: PropTypes.number}).isRequired,
null
null,
);
expectWarningInDevelopment(
PropTypes.shape({key: PropTypes.number}).isRequired,
undefined
undefined,
);
expectWarningInDevelopment(PropTypes.element, <div />);
});
@@ -998,13 +1036,13 @@ describe('ReactPropTypes', () => {
PropTypes.symbol,
'hello',
'Invalid prop `testProp` of type `string` supplied to ' +
'`testComponent`, expected `symbol`.'
'`testComponent`, expected `symbol`.',
);
typeCheckFail(
PropTypes.symbol,
function() { },
function() {},
'Invalid prop `testProp` of type `function` supplied to ' +
'`testComponent`, expected `symbol`.'
'`testComponent`, expected `symbol`.',
);
typeCheckFail(
PropTypes.symbol,
@@ -1012,7 +1050,7 @@ describe('ReactPropTypes', () => {
'@@toStringTag': 'Katana',
},
'Invalid prop `testProp` of type `object` supplied to ' +
'`testComponent`, expected `symbol`.'
'`testComponent`, expected `symbol`.',
);
});
@@ -1061,15 +1099,15 @@ describe('ReactPropTypes', () => {
expect(spy.calls.argsFor(0)[1]).toBe('num');
});
it('should have received the validator\'s return value', () => {
it("should have received the validator's return value", () => {
spyOn(console, 'error');
var spy = jasmine.createSpy().and.callFake(
function(props, propName, componentName) {
var spy = jasmine
.createSpy()
.and.callFake(function(props, propName, componentName) {
if (props[propName] !== 5) {
return new Error('num must be 5!');
}
}
);
});
Component = class extends React.Component {
static propTypes = {num: spy};
@@ -1082,33 +1120,31 @@ describe('ReactPropTypes', () => {
ReactTestUtils.renderIntoDocument(instance);
expect(console.error.calls.count()).toBe(1);
expect(
console.error.calls.argsFor(0)[0].replace(/\(at .+?:\d+\)/g, '(at **)')
console.error.calls.argsFor(0)[0].replace(/\(at .+?:\d+\)/g, '(at **)'),
).toBe(
'Warning: Failed prop type: num must be 5!\n' +
' in Component (at **)'
' in Component (at **)',
);
});
it('should not warn if the validator returned null',
() => {
spyOn(console, 'error');
var spy = jasmine.createSpy().and.callFake(
function(props, propName, componentName) {
return null;
}
);
Component = class extends React.Component {
static propTypes = {num: spy};
it('should not warn if the validator returned null', () => {
spyOn(console, 'error');
var spy = jasmine
.createSpy()
.and.callFake(function(props, propName, componentName) {
return null;
});
Component = class extends React.Component {
static propTypes = {num: spy};
render() {
return <div />;
}
};
render() {
return <div />;
}
};
var instance = <Component num={5} />;
ReactTestUtils.renderIntoDocument(instance);
expect(console.error.calls.count()).toBe(0);
}
);
var instance = <Component num={5} />;
ReactTestUtils.renderIntoDocument(instance);
expect(console.error.calls.count()).toBe(0);
});
});
});
+42 -34
View File
@@ -17,23 +17,26 @@ var ReactCurrentOwner = require('ReactCurrentOwner');
var invariant = require('invariant');
var warning = require('warning');
import type { ReactElement, Source } from 'ReactElementType';
import type { DebugID } from 'ReactInstanceType';
import type {ReactElement, Source} from 'ReactElementType';
import type {DebugID} from 'ReactInstanceType';
function isNative(fn) {
// Based on isNative() from Lodash
var funcToString = Function.prototype.toString;
var hasOwnProperty = Object.prototype.hasOwnProperty;
var reIsNative = RegExp('^' + funcToString
// Take an example native function source for comparison
.call(hasOwnProperty)
// Strip regex characters so we can use it for regex
.replace(/[\\^$.*+?()[\]{}|]/g, '\\$&')
// Remove hasOwnProperty from the template to make it generic
.replace(
/hasOwnProperty|(function).*?(?=\\\()| for .+?(?=\\\])/g,
'$1.*?'
) + '$'
var reIsNative = RegExp(
'^' +
funcToString
// Take an example native function source for comparison
.call(hasOwnProperty)
// Strip regex characters so we can use it for regex
.replace(/[\\^$.*+?()[\]{}|]/g, '\\$&')
// Remove hasOwnProperty from the template to make it generic
.replace(
/hasOwnProperty|(function).*?(?=\\\()| for .+?(?=\\\])/g,
'$1.*?',
) +
'$',
);
try {
var source = funcToString.call(fn);
@@ -43,7 +46,7 @@ function isNative(fn) {
}
}
var canUseCollections = (
var canUseCollections =
// Array.from
typeof Array.from === 'function' &&
// Map
@@ -59,8 +62,7 @@ var canUseCollections = (
// Set.prototype.keys
Set.prototype != null &&
typeof Set.prototype.keys === 'function' &&
isNative(Set.prototype.keys)
);
isNative(Set.prototype.keys);
var setItem;
var getItem;
@@ -96,7 +98,6 @@ if (canUseCollections) {
getRootIDs = function() {
return Array.from(rootIDSet.keys());
};
} else {
var itemByKey = {};
var rootByKey = {};
@@ -151,13 +152,16 @@ function purgeDeep(id) {
}
function describeComponentFrame(name, source, ownerName) {
return '\n in ' + (name || 'Unknown') + (
source ?
' (at ' + source.fileName.replace(/^.*[\\\/]/, '') + ':' +
source.lineNumber + ')' :
ownerName ?
' (created by ' + ownerName + ')' :
''
return (
'\n in ' +
(name || 'Unknown') +
(source
? ' (at ' +
source.fileName.replace(/^.*[\\\/]/, '') +
':' +
source.lineNumber +
')'
: ownerName ? ' (created by ' + ownerName + ')' : '')
);
}
@@ -184,8 +188,8 @@ function describeID(id: DebugID): string {
warning(
element,
'ReactComponentTreeHook: Missing React element for debugID %s when ' +
'building stack',
id
'building stack',
id,
);
return describeComponentFrame(name, element && element._source, ownerName);
}
@@ -202,19 +206,19 @@ var ReactComponentTreeHook = {
invariant(
nextChild,
'Expected hook events to fire for the child ' +
'before its parent includes it in onSetChildren().'
'before its parent includes it in onSetChildren().',
);
invariant(
nextChild.childIDs != null ||
typeof nextChild.element !== 'object' ||
nextChild.element == null,
typeof nextChild.element !== 'object' ||
nextChild.element == null,
'Expected onSetChildren() to fire for a container child ' +
'before its parent includes it in onSetChildren().'
'before its parent includes it in onSetChildren().',
);
invariant(
nextChild.isMounted,
'Expected onMountComponent() to fire for the child ' +
'before its parent includes it in onSetChildren().'
'before its parent includes it in onSetChildren().',
);
if (nextChild.parentID == null) {
nextChild.parentID = id;
@@ -225,15 +229,19 @@ var ReactComponentTreeHook = {
invariant(
nextChild.parentID === id,
'Expected onBeforeMountComponent() parent and onSetChildren() to ' +
'be consistent (%s has parents %s and %s).',
'be consistent (%s has parents %s and %s).',
nextChildID,
nextChild.parentID,
id
id,
);
}
},
onBeforeMountComponent(id: DebugID, element: ReactElement, parentID: DebugID): void {
onBeforeMountComponent(
id: DebugID,
element: ReactElement,
parentID: DebugID,
): void {
var item = {
element,
parentID,
@@ -318,7 +326,7 @@ var ReactComponentTreeHook = {
info += describeComponentFrame(
name,
topElement._source,
owner && owner.getName()
owner && owner.getName(),
);
}
@@ -60,10 +60,10 @@ ReactComponent.prototype.isReactComponent = {};
ReactComponent.prototype.setState = function(partialState, callback) {
invariant(
typeof partialState === 'object' ||
typeof partialState === 'function' ||
partialState == null,
typeof partialState === 'function' ||
partialState == null,
'setState(...): takes an object of state variables to update or a ' +
'function which returns an object of state variables.'
'function which returns an object of state variables.',
);
this.updater.enqueueSetState(this, partialState);
if (callback) {
@@ -102,12 +102,12 @@ if (__DEV__) {
isMounted: [
'isMounted',
'Instead, make sure to clean up subscriptions and pending requests in ' +
'componentWillUnmount to prevent memory leaks.',
'componentWillUnmount to prevent memory leaks.',
],
replaceState: [
'replaceState',
'Refactor your code to use setState instead (see ' +
'https://github.com/facebook/react/issues/3236).',
'https://github.com/facebook/react/issues/3236).',
],
};
var defineDeprecationWarning = function(methodName, info) {
@@ -118,7 +118,7 @@ if (__DEV__) {
false,
'%s(...) is deprecated in plain JavaScript React classes. %s',
info[0],
info[1]
info[1],
);
return undefined;
},
@@ -19,11 +19,12 @@ function warnNoop(publicInstance, callerName) {
warning(
false,
'%s(...): Can only update a mounted or mounting component. ' +
'This usually means you called %s() on an unmounted component. ' +
'This is a no-op. Please check the code for the %s component.',
'This usually means you called %s() on an unmounted component. ' +
'This is a no-op. Please check the code for the %s component.',
callerName,
callerName,
constructor && (constructor.displayName || constructor.name) || 'ReactClass'
(constructor && (constructor.displayName || constructor.name)) ||
'ReactClass',
);
}
}
@@ -32,7 +33,6 @@ function warnNoop(publicInstance, callerName) {
* This is the abstract API for an update queue.
*/
var ReactNoopUpdateQueue = {
/**
* Checks whether or not this composite component is mounted.
* @param {ReactClass} publicInstance The instance we want to test.
@@ -52,7 +52,7 @@ var ReactNoopUpdateQueue = {
* @param {?function} callback Called after state is updated.
* @internal
*/
enqueueCallback: function(publicInstance, callback) { },
enqueueCallback: function(publicInstance, callback) {},
/**
* Forces an update. This should only be invoked when it is known with
@@ -26,7 +26,6 @@ describe('ReactClassEquivalence', () => {
var result2 = runJest('ReactES6Class-test.js');
compareResults(result1, result2);
});
});
function runJest(testFile) {
@@ -35,14 +34,13 @@ function runJest(testFile) {
var setupFile = path.resolve(
'scripts',
'jest',
'setupSpecEquivalenceReporter.js'
'setupSpecEquivalenceReporter.js',
);
var result = spawnSync(
'node',
[jestBin, testFile, '--setupTestFrameworkScriptFile', setupFile],
{cwd},
);
var result = spawnSync('node', [
jestBin,
testFile,
'--setupTestFrameworkScriptFile',
setupFile,
], {cwd});
if (result.error) {
throw result.error;
@@ -51,12 +49,12 @@ function runJest(testFile) {
if (result.status !== 0) {
throw new Error(
'jest process exited with: ' +
result.status +
'\n' +
'stdout: ' +
result.stdout.toString() +
'stderr: ' +
result.stderr.toString()
result.status +
'\n' +
'stdout: ' +
result.stdout.toString() +
'stderr: ' +
result.stderr.toString(),
);
}
@@ -15,7 +15,6 @@ var React;
var ReactDOM;
describe('ReactES6Class', () => {
var container;
var freeze = function(expectation) {
Object.freeze(expectation);
@@ -52,19 +51,19 @@ describe('ReactES6Class', () => {
}
it('preserves the name of the class for use in error messages', () => {
class Foo extends React.Component { }
class Foo extends React.Component {}
expect(Foo.name).toBe('Foo');
});
it('throws if no render function is defined', () => {
spyOn(console, 'error');
class Foo extends React.Component { }
class Foo extends React.Component {}
expect(() => ReactDOM.render(<Foo />, container)).toThrow();
expect(console.error.calls.count()).toBe(1);
expect(console.error.calls.argsFor(0)[0]).toBe(
'Warning: Foo(...): No `render` method found on the returned component ' +
'instance: you may have forgotten to define `render`.'
'instance: you may have forgotten to define `render`.',
);
});
@@ -174,7 +173,7 @@ describe('ReactES6Class', () => {
}
}
expect(() => test(<Foo />, 'span', '')).toThrowError(
'Foo.state: must be set to an object or null'
'Foo.state: must be set to an object or null',
);
});
});
@@ -203,10 +202,7 @@ describe('ReactES6Class', () => {
}
render() {
return (
<Inner
name={this.state.bar}
onClick={this.handleClick.bind(this)}
/>
<Inner name={this.state.bar} onClick={this.handleClick.bind(this)} />
);
}
}
@@ -225,12 +221,7 @@ describe('ReactES6Class', () => {
this.setState({bar: 'bar'});
}
render() {
return (
<Inner
name={this.state.bar}
onClick={this.handleClick}
/>
);
return <Inner name={this.state.bar} onClick={this.handleClick} />;
}
}
test(<Foo initialValue="foo" />, 'DIV', 'foo');
@@ -295,23 +286,25 @@ describe('ReactES6Class', () => {
}
}
test(<Foo value="foo" />, 'SPAN', 'foo');
expect(lifeCycles).toEqual([
'will-mount',
'did-mount',
]);
expect(lifeCycles).toEqual(['will-mount', 'did-mount']);
lifeCycles = []; // reset
test(<Foo value="bar" />, 'SPAN', 'bar');
expect(lifeCycles).toEqual([
'receive-props', freeze({value: 'bar'}),
'should-update', freeze({value: 'bar'}), {},
'will-update', freeze({value: 'bar'}), {},
'did-update', freeze({value: 'foo'}), {},
'receive-props',
freeze({value: 'bar'}),
'should-update',
freeze({value: 'bar'}),
{},
'will-update',
freeze({value: 'bar'}),
{},
'did-update',
freeze({value: 'foo'}),
{},
]);
lifeCycles = []; // reset
ReactDOM.unmountComponentAtNode(container);
expect(lifeCycles).toEqual([
'will-unmount',
]);
expect(lifeCycles).toEqual(['will-unmount']);
});
it('warns when classic properties are defined on the instance, but does not invoke them.', () => {
@@ -341,16 +334,16 @@ describe('ReactES6Class', () => {
expect(getDefaultPropsWasCalled).toBe(false);
expect(console.error.calls.count()).toBe(4);
expect(console.error.calls.argsFor(0)[0]).toContain(
'getInitialState was defined on Foo, a plain JavaScript class.'
'getInitialState was defined on Foo, a plain JavaScript class.',
);
expect(console.error.calls.argsFor(1)[0]).toContain(
'getDefaultProps was defined on Foo, a plain JavaScript class.'
'getDefaultProps was defined on Foo, a plain JavaScript class.',
);
expect(console.error.calls.argsFor(2)[0]).toContain(
'propTypes was defined as an instance property on Foo.'
'propTypes was defined as an instance property on Foo.',
);
expect(console.error.calls.argsFor(3)[0]).toContain(
'contextTypes was defined as an instance property on Foo.'
'contextTypes was defined as an instance property on Foo.',
);
});
@@ -385,9 +378,9 @@ describe('ReactES6Class', () => {
expect(console.error.calls.count()).toBe(1);
expect(console.error.calls.argsFor(0)[0]).toBe(
'Warning: ' +
'NamedComponent has a method called componentShouldUpdate(). Did you ' +
'mean shouldComponentUpdate()? The name is phrased as a question ' +
'because the function is expected to return a value.'
'NamedComponent has a method called componentShouldUpdate(). Did you ' +
'mean shouldComponentUpdate()? The name is phrased as a question ' +
'because the function is expected to return a value.',
);
});
@@ -407,8 +400,8 @@ describe('ReactES6Class', () => {
expect(console.error.calls.count()).toBe(1);
expect(console.error.calls.argsFor(0)[0]).toBe(
'Warning: ' +
'NamedComponent has a method called componentWillRecieveProps(). Did ' +
'you mean componentWillReceiveProps()?'
'NamedComponent has a method called componentWillRecieveProps(). Did ' +
'you mean componentWillReceiveProps()?',
);
});
@@ -419,10 +412,10 @@ describe('ReactES6Class', () => {
expect(() => instance.isMounted()).toThrow();
expect(console.error.calls.count()).toBe(2);
expect(console.error.calls.argsFor(0)[0]).toContain(
'replaceState(...) is deprecated in plain JavaScript React classes'
'replaceState(...) is deprecated in plain JavaScript React classes',
);
expect(console.error.calls.argsFor(1)[0]).toContain(
'isMounted(...) is deprecated in plain JavaScript React classes'
'isMounted(...) is deprecated in plain JavaScript React classes',
);
});
@@ -460,5 +453,4 @@ describe('ReactES6Class', () => {
var node = ReactDOM.findDOMNode(instance);
expect(node).toBe(container.firstChild);
});
});
@@ -93,5 +93,4 @@ describe('ReactPureComponent', () => {
ReactDOM.render(<Component />, document.createElement('div'));
expect(renders).toBe(1);
});
});
@@ -64,7 +64,7 @@ describe('ReactJSXElement', () => {
it('returns an immutable element', () => {
var element = <Component />;
expect(() => element.type = 'div').toThrow();
expect(() => (element.type = 'div')).toThrow();
});
it('does not reuse the object that is spread into props', () => {
@@ -80,7 +80,7 @@ describe('ReactJSXElement', () => {
expect(element.type).toBe(Component);
expect(element.key).toBe('12');
expect(element.ref).toBe('34');
var expectation = {foo:'56'};
var expectation = {foo: '56'};
Object.freeze(expectation);
expect(element.props).toEqual(expectation);
});
@@ -90,7 +90,7 @@ describe('ReactJSXElement', () => {
expect(element.type).toBe(Component);
expect(element.key).toBe('12');
expect(element.ref).toBe(null);
var expectation = {foo:'56'};
var expectation = {foo: '56'};
Object.freeze(expectation);
expect(element.props).toEqual(expectation);
});
@@ -124,7 +124,7 @@ describe('ReactJSXElement', () => {
var element2 = React.cloneElement(
<Component children="text" />,
{},
undefined
undefined,
);
expect(element2.props.children).toBe(undefined);
});
@@ -165,7 +165,7 @@ describe('ReactJSXElement', () => {
expect(React.isValidElement({})).toEqual(false);
expect(React.isValidElement('string')).toEqual(false);
expect(React.isValidElement(Component)).toEqual(false);
expect(React.isValidElement({ type: 'div', props: {} })).toEqual(false);
expect(React.isValidElement({type: 'div', props: {}})).toEqual(false);
});
it('is indistinguishable from a plain object', () => {
@@ -178,10 +178,7 @@ describe('ReactJSXElement', () => {
Component.defaultProps = {fruit: 'persimmon'};
var container = document.createElement('div');
var instance = ReactDOM.render(
<Component fruit="mango" />,
container
);
var instance = ReactDOM.render(<Component fruit="mango" />, container);
expect(instance.props.fruit).toBe('mango');
ReactDOM.render(<Component />, container);
@@ -199,9 +196,9 @@ describe('ReactJSXElement', () => {
var instance = ReactTestUtils.renderIntoDocument(<NormalizingComponent />);
expect(instance.props.prop).toBe('testKey');
var inst2 =
ReactTestUtils.renderIntoDocument(<NormalizingComponent prop={null} />);
var inst2 = ReactTestUtils.renderIntoDocument(
<NormalizingComponent prop={null} />,
);
expect(inst2.props.prop).toBe(null);
});
});
@@ -55,7 +55,7 @@ describe('ReactJSXElementValidator', () => {
expect(console.error.calls.count()).toBe(1);
expect(console.error.calls.argsFor(0)[0]).toContain(
'Each child in an array or iterator should have a unique "key" prop.'
'Each child in an array or iterator should have a unique "key" prop.',
);
});
@@ -70,11 +70,7 @@ describe('ReactJSXElementValidator', () => {
class ComponentWrapper extends React.Component {
render() {
return (
<InnerComponent
childSet={[<Component />, <Component />]}
/>
);
return <InnerComponent childSet={[<Component />, <Component />]} />;
}
}
@@ -83,8 +79,8 @@ describe('ReactJSXElementValidator', () => {
expect(console.error.calls.count()).toBe(1);
expect(console.error.calls.argsFor(0)[0]).toContain(
'Each child in an array or iterator should have a unique "key" prop. ' +
'Check the render method of `InnerComponent`. ' +
'It was passed a child from ComponentWrapper. '
'Check the render method of `InnerComponent`. ' +
'It was passed a child from ComponentWrapper. ',
);
});
@@ -107,14 +103,16 @@ describe('ReactJSXElementValidator', () => {
expect(console.error.calls.count()).toBe(1);
expect(console.error.calls.argsFor(0)[0]).toContain(
'Each child in an array or iterator should have a unique "key" prop.'
'Each child in an array or iterator should have a unique "key" prop.',
);
});
it('does not warns for arrays of elements with keys', () => {
spyOn(console, 'error');
void <Component>{[<Component key="#1" />, <Component key="#2" />]}</Component>;
void (
<Component>{[<Component key="#1" />, <Component key="#2" />]}</Component>
);
expect(console.error.calls.count()).toBe(0);
});
@@ -203,10 +201,10 @@ describe('ReactJSXElementValidator', () => {
ReactTestUtils.renderIntoDocument(<ParentComp />);
expect(normalizeCodeLocInfo(console.error.calls.argsFor(0)[0])).toBe(
'Warning: Failed prop type: ' +
'Invalid prop `color` of type `number` supplied to `MyComp`, ' +
'expected `string`.\n' +
' in MyComp (at **)\n' +
' in ParentComp (at **)'
'Invalid prop `color` of type `number` supplied to `MyComp`, ' +
'expected `string`.\n' +
' in MyComp (at **)\n' +
' in ParentComp (at **)',
);
});
@@ -239,11 +237,11 @@ describe('ReactJSXElementValidator', () => {
// If it doesn't, it means we're using information from the old element.
expect(normalizeCodeLocInfo(console.error.calls.argsFor(0)[0])).toBe(
'Warning: Failed prop type: ' +
'Invalid prop `color` of type `number` supplied to `MyComp`, ' +
'expected `string`.\n' +
' in MyComp (at **)\n' +
' in MiddleComp (at **)\n' +
' in ParentComp (at **)'
'Invalid prop `color` of type `number` supplied to `MyComp`, ' +
'expected `string`.\n' +
' in MyComp (at **)\n' +
' in MiddleComp (at **)\n' +
' in ParentComp (at **)',
);
});
@@ -261,28 +259,28 @@ describe('ReactJSXElementValidator', () => {
expect(console.error.calls.count()).toBe(4);
expect(normalizeCodeLocInfo(console.error.calls.argsFor(0)[0])).toBe(
'Warning: React.createElement: type is invalid -- expected a string ' +
'(for built-in components) or a class/function (for composite ' +
'components) but got: undefined. You likely forgot to export your ' +
'component from the file it\'s defined in. ' +
'Check your code at **.'
'(for built-in components) or a class/function (for composite ' +
'components) but got: undefined. You likely forgot to export your ' +
"component from the file it's defined in. " +
'Check your code at **.',
);
expect(normalizeCodeLocInfo(console.error.calls.argsFor(1)[0])).toBe(
'Warning: React.createElement: type is invalid -- expected a string ' +
'(for built-in components) or a class/function (for composite ' +
'components) but got: null. ' +
'Check your code at **.'
'(for built-in components) or a class/function (for composite ' +
'components) but got: null. ' +
'Check your code at **.',
);
expect(normalizeCodeLocInfo(console.error.calls.argsFor(2)[0])).toBe(
'Warning: React.createElement: type is invalid -- expected a string ' +
'(for built-in components) or a class/function (for composite ' +
'components) but got: boolean. ' +
'Check your code at **.'
'(for built-in components) or a class/function (for composite ' +
'components) but got: boolean. ' +
'Check your code at **.',
);
expect(normalizeCodeLocInfo(console.error.calls.argsFor(3)[0])).toBe(
'Warning: React.createElement: type is invalid -- expected a string ' +
'(for built-in components) or a class/function (for composite ' +
'components) but got: number. ' +
'Check your code at **.'
'(for built-in components) or a class/function (for composite ' +
'components) but got: number. ' +
'Check your code at **.',
);
void <Div />;
expect(console.error.calls.count()).toBe(4);
@@ -298,8 +296,8 @@ describe('ReactJSXElementValidator', () => {
expect(console.error.calls.count()).toBe(1);
expect(normalizeCodeLocInfo(console.error.calls.argsFor(0)[0])).toBe(
'Warning: Failed prop type: The prop `prop` is marked as required in ' +
'`RequiredPropComponent`, but its value is `null`.\n' +
' in RequiredPropComponent (at **)'
'`RequiredPropComponent`, but its value is `null`.\n' +
' in RequiredPropComponent (at **)',
);
});
@@ -311,8 +309,8 @@ describe('ReactJSXElementValidator', () => {
expect(console.error.calls.count()).toBe(1);
expect(normalizeCodeLocInfo(console.error.calls.argsFor(0)[0])).toBe(
'Warning: Failed prop type: The prop `prop` is marked as required in ' +
'`RequiredPropComponent`, but its value is `null`.\n' +
' in RequiredPropComponent (at **)'
'`RequiredPropComponent`, but its value is `null`.\n' +
' in RequiredPropComponent (at **)',
);
});
@@ -325,16 +323,16 @@ describe('ReactJSXElementValidator', () => {
expect(console.error.calls.count()).toBe(2);
expect(normalizeCodeLocInfo(console.error.calls.argsFor(0)[0])).toBe(
'Warning: Failed prop type: ' +
'The prop `prop` is marked as required in `RequiredPropComponent`, but ' +
'its value is `undefined`.\n' +
' in RequiredPropComponent (at **)'
'The prop `prop` is marked as required in `RequiredPropComponent`, but ' +
'its value is `undefined`.\n' +
' in RequiredPropComponent (at **)',
);
expect(normalizeCodeLocInfo(console.error.calls.argsFor(1)[0])).toBe(
'Warning: Failed prop type: ' +
'Invalid prop `prop` of type `number` supplied to ' +
'`RequiredPropComponent`, expected `string`.\n' +
' in RequiredPropComponent (at **)'
'Invalid prop `prop` of type `number` supplied to ' +
'`RequiredPropComponent`, expected `string`.\n' +
' in RequiredPropComponent (at **)',
);
ReactTestUtils.renderIntoDocument(<RequiredPropComponent prop="string" />);
@@ -361,7 +359,7 @@ describe('ReactJSXElementValidator', () => {
expect(console.error.calls.count()).toBe(1);
expect(console.error.calls.argsFor(0)[0]).toContain(
'NullPropTypeComponent: prop type `prop` is invalid; it must be a ' +
'function, usually from React.PropTypes.'
'function, usually from React.PropTypes.',
);
});
@@ -379,7 +377,7 @@ describe('ReactJSXElementValidator', () => {
expect(console.error.calls.count()).toBe(1);
expect(console.error.calls.argsFor(0)[0]).toContain(
'NullContextTypeComponent: context type `prop` is invalid; it must ' +
'be a function, usually from React.PropTypes.'
'be a function, usually from React.PropTypes.',
);
});
@@ -397,8 +395,7 @@ describe('ReactJSXElementValidator', () => {
expect(console.error.calls.count()).toBe(1);
expect(console.error.calls.argsFor(0)[0]).toContain(
'getDefaultProps is only used on classic React.createClass definitions.' +
' Use a static property named `defaultProps` instead.'
' Use a static property named `defaultProps` instead.',
);
});
});
+91 -103
View File
@@ -12,7 +12,7 @@
'use strict';
require('art/modes/current').setCurrent(
require('art/modes/fast-noSideEffects') // Flip this to DOM mode for debugging
require('art/modes/fast-noSideEffects'), // Flip this to DOM mode for debugging
);
const Transform = require('art/core/transform');
@@ -67,8 +67,10 @@ function createComponent(name) {
*/
function injectAfter(parentNode, referenceNode, node) {
let beforeNode;
if (node.parentNode === parentNode &&
node.previousSibling === referenceNode) {
if (
node.parentNode === parentNode &&
node.previousSibling === referenceNode
) {
return;
}
if (referenceNode == null) {
@@ -83,7 +85,7 @@ function injectAfter(parentNode, referenceNode, node) {
// checks and the behavior isn't well-defined.
invariant(
node !== beforeNode,
'ReactART: Can not insert node before itself'
'ReactART: Can not insert node before itself',
);
node.injectBefore(beforeNode);
} else if (node.parentNode !== parentNode) {
@@ -94,7 +96,6 @@ function injectAfter(parentNode, referenceNode, node) {
// ContainerMixin for components that can hold ART nodes
const ContainerMixin = assign({}, ReactMultiChild.Mixin, {
/**
* Moves a child component to the supplied index.
*
@@ -153,11 +154,7 @@ const ContainerMixin = assign({}, ReactMultiChild.Mixin, {
// Shorthands
mountAndInjectChildren: function(children, transaction, context) {
const mountedImages = this.mountChildren(
children,
transaction,
context
);
const mountedImages = this.mountChildren(children, transaction, context);
// Each mount image corresponds to one of the flattened children
let i = 0;
for (let key in this._renderedChildren) {
@@ -168,15 +165,13 @@ const ContainerMixin = assign({}, ReactMultiChild.Mixin, {
i++;
}
}
}
},
});
// Surface is a React DOM Component, not an ART component. It serves as the
// entry point into the ART reconciler.
const Surface = React.createClass({
displayName: 'Surface',
mixins: [ContainerMixin],
@@ -192,15 +187,17 @@ const Surface = React.createClass({
this,
this.props.children,
transaction,
ReactInstanceMap.get(this)._context
ReactInstanceMap.get(this)._context,
);
ReactUpdates.ReactReconcileTransaction.release(transaction);
},
componentDidUpdate: function(oldProps) {
const node = this.node;
if (this.props.width != oldProps.width ||
this.props.height != oldProps.height) {
if (
this.props.width != oldProps.width ||
this.props.height != oldProps.height
) {
node.resize(+this.props.width, +this.props.height);
}
@@ -210,7 +207,7 @@ const Surface = React.createClass({
this,
this.props.children,
transaction,
ReactInstanceMap.get(this)._context
ReactInstanceMap.get(this)._context,
);
ReactUpdates.ReactReconcileTransaction.release(transaction);
@@ -241,8 +238,7 @@ const Surface = React.createClass({
title={props.title}
/>
);
}
},
});
// Various nodes that can go into a surface
@@ -253,11 +249,10 @@ const EventTypes = {
onMouseOut: 'mouseout',
onMouseUp: 'mouseup',
onMouseDown: 'mousedown',
onClick: 'click'
onClick: 'click',
};
const NodeMixin = {
construct: function(element) {
this._currentElement = element;
},
@@ -312,10 +307,12 @@ const NodeMixin = {
applyNodeProps: function(oldProps, props) {
const node = this.node;
const scaleX = props.scaleX != null ? props.scaleX :
props.scale != null ? props.scale : 1;
const scaleY = props.scaleY != null ? props.scaleY :
props.scale != null ? props.scale : 1;
const scaleX = props.scaleX != null
? props.scaleX
: props.scale != null ? props.scale : 1;
const scaleY = props.scaleY != null
? props.scaleY
: props.scale != null ? props.scale : 1;
pooledTransform
.transformTo(1, 0, 0, 1, 0, 0)
@@ -327,9 +324,14 @@ const NodeMixin = {
pooledTransform.transform(props.transform);
}
if (node.xx !== pooledTransform.xx || node.yx !== pooledTransform.yx ||
node.xy !== pooledTransform.xy || node.yy !== pooledTransform.yy ||
node.x !== pooledTransform.x || node.y !== pooledTransform.y) {
if (
node.xx !== pooledTransform.xx ||
node.yx !== pooledTransform.yx ||
node.xy !== pooledTransform.xy ||
node.yy !== pooledTransform.yy ||
node.x !== pooledTransform.x ||
node.y !== pooledTransform.y
) {
node.transformTo(pooledTransform);
}
@@ -357,21 +359,19 @@ const NodeMixin = {
mountComponentIntoNode: function(rootID, container) {
throw new Error(
'You cannot render an ART component standalone. ' +
'You need to wrap it in a Surface.'
'You need to wrap it in a Surface.',
);
}
},
};
// Group
const Group = createComponent('Group', NodeMixin, ContainerMixin, {
mountComponent: function(
transaction,
nativeParent,
nativeContainerInfo,
context
context,
) {
this.node = Mode.Group();
const props = this._currentElement.props;
@@ -397,55 +397,54 @@ const Group = createComponent('Group', NodeMixin, ContainerMixin, {
unmountComponent: function() {
this.destroyEventListeners();
this.unmountChildren();
}
},
});
// ClippingRectangle
const ClippingRectangle = createComponent(
'ClippingRectangle', NodeMixin, ContainerMixin, {
'ClippingRectangle',
NodeMixin,
ContainerMixin,
{
mountComponent: function(
transaction,
nativeParent,
nativeContainerInfo,
context,
) {
this.node = Mode.ClippingRectangle();
const props = this._currentElement.props;
this.applyClippingProps(emptyObject, props);
this.mountAndInjectChildren(props.children, transaction, context);
return this.node;
},
mountComponent: function(
transaction,
nativeParent,
nativeContainerInfo,
context
) {
this.node = Mode.ClippingRectangle();
const props = this._currentElement.props;
this.applyClippingProps(emptyObject, props);
this.mountAndInjectChildren(props.children, transaction, context);
return this.node;
receiveComponent: function(nextComponent, transaction, context) {
const props = nextComponent.props;
const oldProps = this._currentElement.props;
this.applyClippingProps(oldProps, props);
this.updateChildren(props.children, transaction, context);
this._currentElement = nextComponent;
},
applyClippingProps: function(oldProps, props) {
this.node.width = props.width;
this.node.height = props.height;
this.node.x = props.x;
this.node.y = props.y;
this.applyNodeProps(oldProps, props);
},
unmountComponent: function() {
this.destroyEventListeners();
this.unmountChildren();
},
},
receiveComponent: function(nextComponent, transaction, context) {
const props = nextComponent.props;
const oldProps = this._currentElement.props;
this.applyClippingProps(oldProps, props);
this.updateChildren(props.children, transaction, context);
this._currentElement = nextComponent;
},
applyClippingProps: function(oldProps, props) {
this.node.width = props.width;
this.node.height = props.height;
this.node.x = props.x;
this.node.y = props.y;
this.applyNodeProps(oldProps, props);
},
unmountComponent: function() {
this.destroyEventListeners();
this.unmountChildren();
}
});
);
// Renderables
const RenderableMixin = assign({}, NodeMixin, {
applyRenderableProps: function(oldProps, props) {
if (oldProps.fill !== props.fill) {
if (props.fill && props.fill.applyFill) {
@@ -468,7 +467,7 @@ const RenderableMixin = assign({}, NodeMixin, {
props.strokeWidth,
props.strokeCap,
props.strokeJoin,
props.strokeDash
props.strokeDash,
);
}
this.applyNodeProps(oldProps, props);
@@ -476,14 +475,12 @@ const RenderableMixin = assign({}, NodeMixin, {
unmountComponent: function() {
this.destroyEventListeners();
}
},
});
// Shape
const Shape = createComponent('Shape', RenderableMixin, {
construct: function(element) {
this._currentElement = element;
this._oldDelta = null;
@@ -494,7 +491,7 @@ const Shape = createComponent('Shape', RenderableMixin, {
transaction,
nativeParent,
nativeContainerInfo,
context
context,
) {
this.node = Mode.Shape();
const props = this._currentElement.props;
@@ -514,30 +511,25 @@ const Shape = createComponent('Shape', RenderableMixin, {
const oldPath = this._oldPath;
const path = props.d || childrenAsString(props.children);
if (path.delta !== oldDelta ||
path !== oldPath ||
oldProps.width !== props.width ||
oldProps.height !== props.height) {
this.node.draw(
path,
props.width,
props.height
);
if (
path.delta !== oldDelta ||
path !== oldPath ||
oldProps.width !== props.width ||
oldProps.height !== props.height
) {
this.node.draw(path, props.width, props.height);
this._oldPath = path;
this._oldDelta = path.delta;
}
this.applyRenderableProps(oldProps, props);
}
},
});
// Text
const Text = createComponent('Text', RenderableMixin, {
construct: function(element) {
this._currentElement = element;
this._oldString = null;
@@ -547,7 +539,7 @@ const Text = createComponent('Text', RenderableMixin, {
transaction,
nativeParent,
nativeContainerInfo,
context
context,
) {
const props = this._currentElement.props;
const newString = childrenAsString(props.children);
@@ -580,23 +572,19 @@ const Text = createComponent('Text', RenderableMixin, {
const oldString = this._oldString;
const newString = childrenAsString(props.children);
if (oldString !== newString ||
!this.isSameFont(oldProps.font, props.font) ||
oldProps.alignment !== props.alignment ||
oldProps.path !== props.path) {
this.node.draw(
newString,
props.font,
props.alignment,
props.path
);
if (
oldString !== newString ||
!this.isSameFont(oldProps.font, props.font) ||
oldProps.alignment !== props.alignment ||
oldProps.path !== props.path
) {
this.node.draw(newString, props.font, props.alignment, props.path);
this._oldString = newString;
}
this.applyRenderableProps(oldProps, props);
this._currentElement = nextComponent;
}
},
});
// Declarative fill type objects - API design not finalized
+43 -40
View File
@@ -49,7 +49,6 @@ function testDOMNodeStructure(domNode, expectedStructure) {
}
describe('ReactART', () => {
beforeEach(() => {
ARTCurrentMode.setCurrent(ARTSVGMode);
@@ -59,29 +58,33 @@ describe('ReactART', () => {
TestComponent = class extends React.Component {
render() {
var a =
var a = (
<Shape
d="M0,0l50,0l0,50l-50,0z"
fill={new ReactART.LinearGradient(["black", "white"])}
fill={new ReactART.LinearGradient(['black', 'white'])}
key="a"
width={50} height={50}
x={50} y={50}
width={50}
height={50}
x={50}
y={50}
opacity={0.1}
/>;
/>
);
var b =
var b = (
<Shape
fill="#3C5A99"
key="b"
scale={0.5}
x={50} y={50}
x={50}
y={50}
title="This is an F"
cursor="pointer">
M64.564,38.583H54l0.008-5.834c0-3.035,0.293-4.666,4.657-4.666
h5.833V16.429h-9.33c-11.213,0-15.159,5.654-15.159,15.16v6.994
h-6.99v11.652h6.99v33.815H54V50.235h9.331L64.564,38.583z
</Shape>;
</Shape>
);
var c = <Group key="c" />;
@@ -113,22 +116,20 @@ describe('ReactART', () => {
width: '150',
height: '200',
children: [
{ nodeName: 'defs' },
{nodeName: 'defs'},
{
nodeName: 'g',
children: [
{
nodeName: 'defs',
children: [
{ nodeName: 'linearGradient' }
]
children: [{nodeName: 'linearGradient'}],
},
{ nodeName: 'path' },
{ nodeName: 'path' },
{ nodeName: 'g' }
]
}
]
{nodeName: 'path'},
{nodeName: 'path'},
{nodeName: 'g'},
],
},
],
};
var realNode = ReactDOM.findDOMNode(instance);
@@ -137,22 +138,25 @@ describe('ReactART', () => {
it('should be able to reorder components', () => {
var container = document.createElement('div');
var instance = ReactDOM.render(<TestComponent flipped={false} />, container);
var instance = ReactDOM.render(
<TestComponent flipped={false} />,
container,
);
var expectedStructure = {
nodeName: 'svg',
children: [
{ nodeName: 'defs' },
{nodeName: 'defs'},
{
nodeName: 'g',
children: [
{ nodeName: 'defs' },
{ nodeName: 'path', opacity: '0.1' },
{ nodeName: 'path', opacity: Missing },
{ nodeName: 'g' }
]
}
]
{nodeName: 'defs'},
{nodeName: 'path', opacity: '0.1'},
{nodeName: 'path', opacity: Missing},
{nodeName: 'g'},
],
},
],
};
var realNode = ReactDOM.findDOMNode(instance);
@@ -163,17 +167,17 @@ describe('ReactART', () => {
var expectedNewStructure = {
nodeName: 'svg',
children: [
{ nodeName: 'defs' },
{nodeName: 'defs'},
{
nodeName: 'g',
children: [
{ nodeName: 'defs' },
{ nodeName: 'path', opacity: Missing },
{ nodeName: 'path', opacity: '0.1' },
{ nodeName: 'g' }
]
}
]
{nodeName: 'defs'},
{nodeName: 'path', opacity: Missing},
{nodeName: 'path', opacity: '0.1'},
{nodeName: 'g'},
],
},
],
};
testDOMNodeStructure(realNode, expectedNewStructure);
@@ -187,7 +191,7 @@ describe('ReactART', () => {
var chars = this.props.chars.split('');
return (
<Surface>
{chars.map((text) => <Shape key={text} title={text} />)}
{chars.map(text => <Shape key={text} title={text} />)}
</Surface>
);
}
@@ -225,7 +229,7 @@ describe('ReactART', () => {
<Group>
<CustomShape />
</Group>
</Surface>
</Surface>,
);
expect(mounted).toBe(true);
});
@@ -294,5 +298,4 @@ describe('ReactART', () => {
ReactDOM.render(<Outer mountCustomShape={true} />, container);
expect(ref.constructor).toBe(CustomShape);
});
});
+21 -17
View File
@@ -43,11 +43,11 @@ var ReactDOM = {
// Allows for debugging when the hook is injected on the page.
if (
typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ !== 'undefined' &&
typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.inject === 'function') {
typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.inject === 'function'
) {
__REACT_DEVTOOLS_GLOBAL_HOOK__.inject({
ComponentTree: {
getClosestInstanceFromNode:
ReactDOMComponentTree.getClosestInstanceFromNode,
getClosestInstanceFromNode: ReactDOMComponentTree.getClosestInstanceFromNode,
getNodeFromInstance: function(inst) {
// inst is an internal instance (but could be a composite)
if (inst._renderedComponent) {
@@ -68,21 +68,25 @@ if (
if (__DEV__) {
var ExecutionEnvironment = require('ExecutionEnvironment');
if (ExecutionEnvironment.canUseDOM && window.top === window.self) {
// First check if devtools is not installed
if (typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ === 'undefined') {
// If we're in Chrome or Firefox, provide a download link if not installed.
if ((navigator.userAgent.indexOf('Chrome') > -1 &&
if (
(navigator.userAgent.indexOf('Chrome') > -1 &&
navigator.userAgent.indexOf('Edge') === -1) ||
navigator.userAgent.indexOf('Firefox') > -1) {
navigator.userAgent.indexOf('Firefox') > -1
) {
// Firefox does not have the issue with devtools loaded over file://
var showFileUrlMessage = window.location.protocol.indexOf('http') === -1 &&
var showFileUrlMessage =
window.location.protocol.indexOf('http') === -1 &&
navigator.userAgent.indexOf('Firefox') === -1;
console.debug(
'Download the React DevTools ' +
(showFileUrlMessage ? 'and use an HTTP server (instead of a file: URL) ' : '') +
'for a better development experience: ' +
'https://fb.me/react-devtools'
(showFileUrlMessage
? 'and use an HTTP server (instead of a file: URL) '
: '') +
'for a better development experience: ' +
'https://fb.me/react-devtools',
);
}
}
@@ -90,10 +94,10 @@ if (__DEV__) {
var testFunc = function testFn() {};
warning(
(testFunc.name || testFunc.toString()).indexOf('testFn') !== -1,
'It looks like you\'re using a minified copy of the development build ' +
'of React. When deploying React apps to production, make sure to use ' +
'the production build which skips development warnings and is faster. ' +
'See https://fb.me/react-minification for more details.'
"It looks like you're using a minified copy of the development build " +
'of React. When deploying React apps to production, make sure to use ' +
'the production build which skips development warnings and is faster. ' +
'See https://fb.me/react-minification for more details.',
);
// If we're in IE8, check to see if we are in compatibility mode and provide
@@ -104,8 +108,8 @@ if (__DEV__) {
warning(
!ieCompatibilityMode,
'Internet Explorer is running in compatibility mode; please add the ' +
'following tag to your HTML to prevent this from happening: ' +
'<meta http-equiv="X-UA-Compatible" content="IE=edge" />'
'following tag to your HTML to prevent this from happening: ' +
'<meta http-equiv="X-UA-Compatible" content="IE=edge" />',
);
var expectedFeatures = [
@@ -126,7 +130,7 @@ if (__DEV__) {
warning(
false,
'One or more ES5 shims expected by React are not available: ' +
'https://fb.me/react-warning-polyfills'
'https://fb.me/react-warning-polyfills',
);
break;
}
+3 -2
View File
@@ -13,5 +13,6 @@ var ReactDOMFeatureFlags = require('ReactDOMFeatureFlags');
var useFiber = ReactDOMFeatureFlags.useFiber;
module.exports =
useFiber ? require('ReactDOMFiber') : require.requireActual('ReactDOM');
module.exports = useFiber
? require('ReactDOMFiber')
: require.requireActual('ReactDOM');
@@ -62,7 +62,7 @@ describe('ReactDOMProduction', () => {
<Component key={2}>B</Component>
<Component key={3}>C</Component>
</div>,
container
container,
);
expect(container.firstChild).toBe(inst);
@@ -75,7 +75,7 @@ describe('ReactDOMProduction', () => {
<Component key={1}>A</Component>
<Component key={3}>C</Component>
</div>,
container
container,
);
expect(inst.className).toBe('red');
@@ -119,10 +119,7 @@ describe('ReactDOMProduction', () => {
}
var container = document.createElement('div');
var inst = ReactDOM.render(
<Component x={1} />,
container
);
var inst = ReactDOM.render(<Component x={1} />, container);
expect(log).toEqual([
['componentWillMount'],
['render'],
@@ -140,15 +137,10 @@ describe('ReactDOMProduction', () => {
log = [];
inst.setState({y: 2});
expect(log).toEqual([
['shouldComponentUpdate', {x: 1}, {y: 2}],
]);
expect(log).toEqual([['shouldComponentUpdate', {x: 1}, {y: 2}]]);
log = [];
ReactDOM.render(
<Component x={2} />,
container
);
ReactDOM.render(<Component x={2} />, container);
expect(log).toEqual([
['componentWillReceiveProps', {x: 2}],
['shouldComponentUpdate', {x: 2}, {y: 2}],
@@ -158,10 +150,7 @@ describe('ReactDOMProduction', () => {
]);
log = [];
ReactDOM.render(
<Component x={2} />,
container
);
ReactDOM.render(<Component x={2} />, container);
expect(log).toEqual([
['componentWillReceiveProps', {x: 2}],
['shouldComponentUpdate', {x: 2}, {y: 2}],
@@ -169,9 +158,7 @@ describe('ReactDOMProduction', () => {
log = [];
ReactDOM.unmountComponentAtNode(container);
expect(log).toEqual([
['componentWillUnmount'],
]);
expect(log).toEqual([['componentWillUnmount']]);
});
it('should throw with an error code in production', () => {
@@ -186,9 +173,9 @@ describe('ReactDOMProduction', () => {
ReactDOM.render(<Component />, container);
}).toThrowError(
'Minified React error #109; visit ' +
'http://facebook.github.io/react/docs/error-decoder.html?invariant=109&args[]=Component' +
' for the full message or use the non-minified dev environment' +
' for full errors and additional helpful warnings.'
'http://facebook.github.io/react/docs/error-decoder.html?invariant=109&args[]=Component' +
' for the full message or use the non-minified dev environment' +
' for full errors and additional helpful warnings.',
);
});
});
@@ -84,8 +84,10 @@ var reactTopListenersCounter = 0;
var topEventMapping = {
topAbort: 'abort',
topAnimationEnd: getVendorPrefixedEventName('animationend') || 'animationend',
topAnimationIteration: getVendorPrefixedEventName('animationiteration') || 'animationiteration',
topAnimationStart: getVendorPrefixedEventName('animationstart') || 'animationstart',
topAnimationIteration: getVendorPrefixedEventName('animationiteration') ||
'animationiteration',
topAnimationStart: getVendorPrefixedEventName('animationstart') ||
'animationstart',
topBlur: 'blur',
topCanPlay: 'canplay',
topCanPlayThrough: 'canplaythrough',
@@ -142,7 +144,8 @@ var topEventMapping = {
topTouchEnd: 'touchend',
topTouchMove: 'touchmove',
topTouchStart: 'touchstart',
topTransitionEnd: getVendorPrefixedEventName('transitionend') || 'transitionend',
topTransitionEnd: getVendorPrefixedEventName('transitionend') ||
'transitionend',
topVolumeChange: 'volumechange',
topWaiting: 'waiting',
topWheel: 'wheel',
@@ -174,7 +177,6 @@ function getListeningForDocument(mountAt) {
* @internal
*/
var ReactBrowserEventEmitter = Object.assign({}, ReactEventEmitterMixin, {
/**
* Injectable event backend
*/
@@ -186,7 +188,7 @@ var ReactBrowserEventEmitter = Object.assign({}, ReactEventEmitterMixin, {
*/
injectReactEventListener: function(ReactEventListener) {
ReactEventListener.setHandleTopLevel(
ReactBrowserEventEmitter.handleTopLevel
ReactBrowserEventEmitter.handleTopLevel,
);
ReactBrowserEventEmitter.ReactEventListener = ReactEventListener;
},
@@ -207,10 +209,8 @@ var ReactBrowserEventEmitter = Object.assign({}, ReactEventEmitterMixin, {
* @return {boolean} True if callbacks are enabled.
*/
isEnabled: function() {
return !!(
ReactBrowserEventEmitter.ReactEventListener &&
ReactBrowserEventEmitter.ReactEventListener.isEnabled()
);
return !!(ReactBrowserEventEmitter.ReactEventListener &&
ReactBrowserEventEmitter.ReactEventListener.isEnabled());
},
/**
@@ -242,22 +242,21 @@ var ReactBrowserEventEmitter = Object.assign({}, ReactEventEmitterMixin, {
for (var i = 0; i < dependencies.length; i++) {
var dependency = dependencies[i];
if (!(
isListening.hasOwnProperty(dependency) &&
isListening[dependency]
)) {
if (
!(isListening.hasOwnProperty(dependency) && isListening[dependency])
) {
if (dependency === 'topWheel') {
if (isEventSupported('wheel')) {
ReactBrowserEventEmitter.ReactEventListener.trapBubbledEvent(
'topWheel',
'wheel',
mountAt
mountAt,
);
} else if (isEventSupported('mousewheel')) {
ReactBrowserEventEmitter.ReactEventListener.trapBubbledEvent(
'topWheel',
'mousewheel',
mountAt
mountAt,
);
} else {
// Firefox needs to capture a different mouse scroll event.
@@ -265,37 +264,34 @@ var ReactBrowserEventEmitter = Object.assign({}, ReactEventEmitterMixin, {
ReactBrowserEventEmitter.ReactEventListener.trapBubbledEvent(
'topWheel',
'DOMMouseScroll',
mountAt
mountAt,
);
}
} else if (dependency === 'topScroll') {
if (isEventSupported('scroll', true)) {
ReactBrowserEventEmitter.ReactEventListener.trapCapturedEvent(
'topScroll',
'scroll',
mountAt
mountAt,
);
} else {
ReactBrowserEventEmitter.ReactEventListener.trapBubbledEvent(
'topScroll',
'scroll',
ReactBrowserEventEmitter.ReactEventListener.WINDOW_HANDLE
ReactBrowserEventEmitter.ReactEventListener.WINDOW_HANDLE,
);
}
} else if (dependency === 'topFocus' ||
dependency === 'topBlur') {
} else if (dependency === 'topFocus' || dependency === 'topBlur') {
if (isEventSupported('focus', true)) {
ReactBrowserEventEmitter.ReactEventListener.trapCapturedEvent(
'topFocus',
'focus',
mountAt
mountAt,
);
ReactBrowserEventEmitter.ReactEventListener.trapCapturedEvent(
'topBlur',
'blur',
mountAt
mountAt,
);
} else if (isEventSupported('focusin')) {
// IE has `focusin` and `focusout` events which bubble.
@@ -303,12 +299,12 @@ var ReactBrowserEventEmitter = Object.assign({}, ReactEventEmitterMixin, {
ReactBrowserEventEmitter.ReactEventListener.trapBubbledEvent(
'topFocus',
'focusin',
mountAt
mountAt,
);
ReactBrowserEventEmitter.ReactEventListener.trapBubbledEvent(
'topBlur',
'focusout',
mountAt
mountAt,
);
}
@@ -319,7 +315,7 @@ var ReactBrowserEventEmitter = Object.assign({}, ReactEventEmitterMixin, {
ReactBrowserEventEmitter.ReactEventListener.trapBubbledEvent(
dependency,
topEventMapping[dependency],
mountAt
mountAt,
);
}
@@ -332,7 +328,7 @@ var ReactBrowserEventEmitter = Object.assign({}, ReactEventEmitterMixin, {
return ReactBrowserEventEmitter.ReactEventListener.trapBubbledEvent(
topLevelType,
handlerBaseName,
handle
handle,
);
},
@@ -340,7 +336,7 @@ var ReactBrowserEventEmitter = Object.assign({}, ReactEventEmitterMixin, {
return ReactBrowserEventEmitter.ReactEventListener.trapCapturedEvent(
topLevelType,
handlerBaseName,
handle
handle,
);
},
@@ -378,7 +374,6 @@ var ReactBrowserEventEmitter = Object.assign({}, ReactEventEmitterMixin, {
isMonitoringScrollValue = true;
}
},
});
module.exports = ReactBrowserEventEmitter;
@@ -26,12 +26,12 @@ var internalInstanceKey =
* Check if a given node should be cached.
*/
function shouldPrecacheNode(node, nodeID) {
return (node.nodeType === 1 &&
node.getAttribute(ATTR_NAME) === String(nodeID)) ||
(node.nodeType === 8 &&
node.nodeValue === ' react-text: ' + nodeID + ' ') ||
(node.nodeType === 8 &&
node.nodeValue === ' react-empty: ' + nodeID + ' ');
return (
(node.nodeType === 1 && node.getAttribute(ATTR_NAME) === String(nodeID)) ||
(node.nodeType === 8 &&
node.nodeValue === ' react-text: ' + nodeID + ' ') ||
(node.nodeType === 8 && node.nodeValue === ' react-empty: ' + nodeID + ' ')
);
}
/**
@@ -166,7 +166,7 @@ function getNodeFromInstance(inst) {
// invariant for a missing parent, which is super confusing.
invariant(
inst._hostNode !== undefined,
'getNodeFromInstance: Invalid argument.'
'getNodeFromInstance: Invalid argument.',
);
if (inst._hostNode) {
@@ -179,7 +179,7 @@ function getNodeFromInstance(inst) {
parents.push(inst);
invariant(
inst._hostParent,
'React DOM tree root should always have a node reference.'
'React DOM tree root should always have a node reference.',
);
inst = inst._hostParent;
}
@@ -18,7 +18,6 @@ var ReactDOMComponentTree = require('ReactDOMComponentTree');
* Operations used to process updates to DOM nodes.
*/
var ReactDOMIDOperations = {
/**
* Updates a component's children by processing a series of updates.
*
@@ -99,7 +99,7 @@ function getModernOffsets(node) {
selection.anchorNode,
selection.anchorOffset,
selection.focusNode,
selection.focusOffset
selection.focusOffset,
);
var rangeLength = isSelectionCollapsed ? 0 : currentRange.toString().length;
@@ -112,7 +112,7 @@ function getModernOffsets(node) {
tempRange.startContainer,
tempRange.startOffset,
tempRange.endContainer,
tempRange.endOffset
tempRange.endOffset,
);
var start = isTempRangeCollapsed ? 0 : tempRange.toString().length;
@@ -176,8 +176,7 @@ function setModernOffsets(node, offsets) {
var selection = window.getSelection();
var length = node[getTextContentAccessor()].length;
var start = Math.min(offsets.start, length);
var end = offsets.end === undefined ?
start : Math.min(offsets.end, length);
var end = offsets.end === undefined ? start : Math.min(offsets.end, length);
// IE 11 uses modern selection, but doesn't support the extend method.
// Flip backward selections, so we can set with a single range.
@@ -205,11 +204,10 @@ function setModernOffsets(node, offsets) {
}
}
var useIEOffsets = (
var useIEOffsets =
ExecutionEnvironment.canUseDOM &&
'selection' in document &&
!('getSelection' in window)
);
!('getSelection' in window);
var ReactDOMSelection = {
/**
@@ -89,7 +89,7 @@ function traverseTwoPhase(inst, fn, arg) {
inst = inst._hostParent;
}
var i;
for (i = path.length; i-- > 0;) {
for (i = path.length; i-- > 0; ) {
fn(path[i], 'captured', arg);
}
for (i = 0; i < path.length; i++) {
@@ -120,7 +120,7 @@ function traverseEnterLeave(from, to, fn, argFrom, argTo) {
for (i = 0; i < pathFrom.length; i++) {
fn(pathFrom[i], 'bubbled', argFrom);
}
for (i = pathTo.length; i-- > 0;) {
for (i = pathTo.length; i-- > 0; ) {
fn(pathTo[i], 'captured', argTo);
}
}
@@ -52,13 +52,13 @@ Object.assign(TopLevelCallbackBookKeeping.prototype, {
});
PooledClass.addPoolingTo(
TopLevelCallbackBookKeeping,
PooledClass.twoArgumentPooler
PooledClass.twoArgumentPooler,
);
function handleTopLevelImpl(bookKeeping) {
var nativeEventTarget = getEventTarget(bookKeeping.nativeEvent);
var targetInst = ReactDOMComponentTree.getClosestInstanceFromNode(
nativeEventTarget
nativeEventTarget,
);
// Loop through the hierarchy, in case there's any nested components.
@@ -77,7 +77,7 @@ function handleTopLevelImpl(bookKeeping) {
bookKeeping.topLevelType,
targetInst,
bookKeeping.nativeEvent,
getEventTarget(bookKeeping.nativeEvent)
getEventTarget(bookKeeping.nativeEvent),
);
}
}
@@ -105,7 +105,6 @@ var ReactEventListener = {
return ReactEventListener._enabled;
},
/**
* Traps top-level events by using event bubbling.
*
@@ -123,7 +122,7 @@ var ReactEventListener = {
return EventListener.listen(
element,
handlerBaseName,
ReactEventListener.dispatchEvent.bind(null, topLevelType)
ReactEventListener.dispatchEvent.bind(null, topLevelType),
);
},
@@ -144,7 +143,7 @@ var ReactEventListener = {
return EventListener.capture(
element,
handlerBaseName,
ReactEventListener.dispatchEvent.bind(null, topLevelType)
ReactEventListener.dispatchEvent.bind(null, topLevelType),
);
},
@@ -160,7 +159,7 @@ var ReactEventListener = {
var bookKeeping = TopLevelCallbackBookKeeping.getPooled(
topLevelType,
nativeEvent
nativeEvent,
);
try {
// Event queue being processed in the same cycle allows
+18 -19
View File
@@ -28,13 +28,13 @@ function isInDocument(node) {
* Input selection module for React.
*/
var ReactInputSelection = {
hasSelectionCapabilities: function(elem) {
var nodeName = elem && elem.nodeName && elem.nodeName.toLowerCase();
return nodeName && (
(nodeName === 'input' && elem.type === 'text') ||
nodeName === 'textarea' ||
elem.contentEditable === 'true'
return (
nodeName &&
((nodeName === 'input' && elem.type === 'text') ||
nodeName === 'textarea' ||
elem.contentEditable === 'true')
);
},
@@ -42,10 +42,9 @@ var ReactInputSelection = {
var focusedElem = getActiveElement();
return {
focusedElem: focusedElem,
selectionRange:
ReactInputSelection.hasSelectionCapabilities(focusedElem) ?
ReactInputSelection.getSelection(focusedElem) :
null,
selectionRange: ReactInputSelection.hasSelectionCapabilities(focusedElem)
? ReactInputSelection.getSelection(focusedElem)
: null,
};
},
@@ -58,13 +57,9 @@ var ReactInputSelection = {
var curFocusedElem = getActiveElement();
var priorFocusedElem = priorSelectionInformation.focusedElem;
var priorSelectionRange = priorSelectionInformation.selectionRange;
if (curFocusedElem !== priorFocusedElem &&
isInDocument(priorFocusedElem)) {
if (curFocusedElem !== priorFocusedElem && isInDocument(priorFocusedElem)) {
if (ReactInputSelection.hasSelectionCapabilities(priorFocusedElem)) {
ReactInputSelection.setSelection(
priorFocusedElem,
priorSelectionRange
);
ReactInputSelection.setSelection(priorFocusedElem, priorSelectionRange);
}
focusNode(priorFocusedElem);
}
@@ -85,8 +80,10 @@ var ReactInputSelection = {
start: input.selectionStart,
end: input.selectionEnd,
};
} else if (document.selection &&
(input.nodeName && input.nodeName.toLowerCase() === 'input')) {
} else if (
document.selection &&
(input.nodeName && input.nodeName.toLowerCase() === 'input')
) {
// IE8 input.
var range = document.selection.createRange();
// There can only be one selection per document in IE, so it must
@@ -121,8 +118,10 @@ var ReactInputSelection = {
if ('selectionStart' in input) {
input.selectionStart = start;
input.selectionEnd = Math.min(end, input.value.length);
} else if (document.selection &&
(input.nodeName && input.nodeName.toLowerCase() === 'input')) {
} else if (
document.selection &&
(input.nodeName && input.nodeName.toLowerCase() === 'input')
) {
var range = input.createTextRange();
range.collapse(true);
range.moveStart('character', start);
+145 -122
View File
@@ -80,7 +80,7 @@ function internalGetID(node) {
// If node is something like a window, document, or text node, none of
// which support attributes or a .getAttribute method, gracefully return
// the empty string, as if the attribute were missing.
return node.getAttribute && node.getAttribute(ATTR_NAME) || '';
return (node.getAttribute && node.getAttribute(ATTR_NAME)) || '';
}
/**
@@ -96,16 +96,15 @@ function mountComponentIntoNode(
container,
transaction,
shouldReuseMarkup,
context
context,
) {
var markerName;
if (ReactFeatureFlags.logTopLevelRenders) {
var wrappedElement = wrapperInstance._currentElement.props.child;
var type = wrappedElement.type;
markerName = 'React mount: ' + (
typeof type === 'string' ? type :
type.displayName || type.name
);
markerName =
'React mount: ' +
(typeof type === 'string' ? type : type.displayName || type.name);
console.time(markerName);
}
@@ -115,7 +114,7 @@ function mountComponentIntoNode(
null,
ReactDOMContainerInfo(wrapperInstance, container),
context,
0 /* parentDebugID */
0 /* parentDebugID */,
);
if (markerName) {
@@ -128,7 +127,7 @@ function mountComponentIntoNode(
container,
wrapperInstance,
shouldReuseMarkup,
transaction
transaction,
);
}
@@ -143,11 +142,11 @@ function batchedMountComponentIntoNode(
componentInstance,
container,
shouldReuseMarkup,
context
context,
) {
var transaction = ReactUpdates.ReactReconcileTransaction.getPooled(
/* useCreateElement */
!shouldReuseMarkup && ReactDOMFeatureFlags.useCreateElement
!shouldReuseMarkup && ReactDOMFeatureFlags.useCreateElement,
);
transaction.perform(
mountComponentIntoNode,
@@ -156,7 +155,7 @@ function batchedMountComponentIntoNode(
container,
transaction,
shouldReuseMarkup,
context
context,
);
ReactUpdates.ReactReconcileTransaction.release(transaction);
}
@@ -217,7 +216,9 @@ function hasNonRootReactChild(container) {
*/
function nodeIsRenderedByOtherInstance(container) {
var rootEl = getReactRootElementInContainer(container);
return !!(rootEl && isReactNode(rootEl) && !ReactDOMComponentTree.getInstanceFromNode(rootEl));
return !!(rootEl &&
isReactNode(rootEl) &&
!ReactDOMComponentTree.getInstanceFromNode(rootEl));
}
/**
@@ -228,11 +229,10 @@ function nodeIsRenderedByOtherInstance(container) {
* @internal
*/
function isValidContainer(node) {
return !!(node && (
node.nodeType === ELEMENT_NODE_TYPE ||
node.nodeType === DOC_NODE_TYPE ||
node.nodeType === DOCUMENT_FRAGMENT_NODE_TYPE
));
return !!(node &&
(node.nodeType === ELEMENT_NODE_TYPE ||
node.nodeType === DOC_NODE_TYPE ||
node.nodeType === DOCUMENT_FRAGMENT_NODE_TYPE));
}
/**
@@ -243,17 +243,19 @@ function isValidContainer(node) {
* @internal
*/
function isReactNode(node) {
return isValidContainer(node) && (node.hasAttribute(ROOT_ATTR_NAME) || node.hasAttribute(ATTR_NAME));
return (
isValidContainer(node) &&
(node.hasAttribute(ROOT_ATTR_NAME) || node.hasAttribute(ATTR_NAME))
);
}
function getHostRootInstanceInContainer(container) {
var rootEl = getReactRootElementInContainer(container);
var prevHostInstance =
rootEl && ReactDOMComponentTree.getInstanceFromNode(rootEl);
return (
prevHostInstance && !prevHostInstance._hostParent ?
prevHostInstance : null
);
return prevHostInstance && !prevHostInstance._hostParent
? prevHostInstance
: null;
}
function getTopLevelWrapperInContainer(container) {
@@ -298,7 +300,6 @@ TopLevelWrapper.isReactTopLevelWrapper = true;
* Inside of `container`, the first element rendered is the "reactRoot".
*/
var ReactMount = {
TopLevelWrapper: TopLevelWrapper,
/**
@@ -326,13 +327,18 @@ var ReactMount = {
* @param {?function} callback function triggered on completion
*/
_updateRootComponent: function(
prevComponent,
nextElement,
nextContext,
container,
callback) {
prevComponent,
nextElement,
nextContext,
container,
callback,
) {
ReactMount.scrollMonitor(container, function() {
ReactUpdateQueue.enqueueElementInternal(prevComponent, nextElement, nextContext);
ReactUpdateQueue.enqueueElementInternal(
prevComponent,
nextElement,
nextContext,
);
if (callback) {
ReactUpdateQueue.enqueueCallbackInternal(prevComponent, callback);
}
@@ -353,7 +359,7 @@ var ReactMount = {
nextElement,
container,
shouldReuseMarkup,
context
context,
) {
// Various parts of our code (such as ReactCompositeComponent's
// _renderValidatedComponent) assume that calls to render aren't nested;
@@ -361,16 +367,16 @@ var ReactMount = {
warning(
ReactCurrentOwner.current == null,
'_renderNewRootComponent(): Render methods should be a pure function ' +
'of props and state; triggering nested component updates from ' +
'render is not allowed. If necessary, trigger nested updates in ' +
'componentDidUpdate. Check the render method of %s.',
ReactCurrentOwner.current && ReactCurrentOwner.current.getName() ||
'ReactCompositeComponent'
'of props and state; triggering nested component updates from ' +
'render is not allowed. If necessary, trigger nested updates in ' +
'componentDidUpdate. Check the render method of %s.',
(ReactCurrentOwner.current && ReactCurrentOwner.current.getName()) ||
'ReactCompositeComponent',
);
invariant(
isValidContainer(container),
'_registerComponent(...): Target container is not a DOM element.'
'_registerComponent(...): Target container is not a DOM element.',
);
ReactBrowserEventEmitter.ensureScrollValueMonitoring();
@@ -385,7 +391,7 @@ var ReactMount = {
componentInstance,
container,
shouldReuseMarkup,
context
context,
);
var wrapperID = componentInstance._instance.rootID;
@@ -407,53 +413,61 @@ var ReactMount = {
* @param {?function} callback function triggered on completion
* @return {ReactComponent} Component instance rendered in `container`.
*/
renderSubtreeIntoContainer: function(parentComponent, nextElement, container, callback) {
renderSubtreeIntoContainer: function(
parentComponent,
nextElement,
container,
callback,
) {
invariant(
parentComponent != null && ReactInstanceMap.has(parentComponent),
'parentComponent must be a valid React Component'
'parentComponent must be a valid React Component',
);
return ReactMount._renderSubtreeIntoContainer(
parentComponent,
nextElement,
container,
callback
callback,
);
},
_renderSubtreeIntoContainer: function(parentComponent, nextElement, container, callback) {
_renderSubtreeIntoContainer: function(
parentComponent,
nextElement,
container,
callback,
) {
ReactUpdateQueue.validateCallback(callback, 'ReactDOM.render');
invariant(
React.isValidElement(nextElement),
'ReactDOM.render(): Invalid component element.%s',
(
typeof nextElement === 'string' ?
' Instead of passing a string like \'div\', pass ' +
'React.createElement(\'div\') or <div />.' :
typeof nextElement === 'function' ?
' Instead of passing a class like Foo, pass ' +
'React.createElement(Foo) or <Foo />.' :
// Check if it quacks like an element
nextElement != null && nextElement.props !== undefined ?
' This may be caused by unintentionally loading two independent ' +
'copies of React.' :
''
)
typeof nextElement === 'string'
? " Instead of passing a string like 'div', pass " +
"React.createElement('div') or <div />."
: typeof nextElement === 'function'
? ' Instead of passing a class like Foo, pass ' +
'React.createElement(Foo) or <Foo />.'
: // Check if it quacks like an element
nextElement != null && nextElement.props !== undefined
? ' This may be caused by unintentionally loading two independent ' +
'copies of React.'
: '',
);
warning(
!container || !container.tagName ||
container.tagName.toUpperCase() !== 'BODY',
!container ||
!container.tagName ||
container.tagName.toUpperCase() !== 'BODY',
'render(): Rendering components directly into document.body is ' +
'discouraged, since its children are often manipulated by third-party ' +
'scripts and browser extensions. This may lead to subtle ' +
'reconciliation issues. Try rendering into a container element created ' +
'for your app.'
'discouraged, since its children are often manipulated by third-party ' +
'scripts and browser extensions. This may lead to subtle ' +
'reconciliation issues. Try rendering into a container element created ' +
'for your app.',
);
var nextWrappedElement = React.createElement(
TopLevelWrapper,
{ child: nextElement }
);
var nextWrappedElement = React.createElement(TopLevelWrapper, {
child: nextElement,
});
var nextContext;
if (parentComponent) {
@@ -470,15 +484,17 @@ var ReactMount = {
var prevElement = prevWrappedElement.props.child;
if (shouldUpdateReactComponent(prevElement, nextElement)) {
var publicInst = prevComponent._renderedComponent.getPublicInstance();
var updatedCallback = callback && function() {
callback.call(publicInst);
};
var updatedCallback =
callback &&
function() {
callback.call(publicInst);
};
ReactMount._updateRootComponent(
prevComponent,
nextWrappedElement,
nextContext,
container,
updatedCallback
updatedCallback,
);
return publicInst;
} else {
@@ -495,9 +511,9 @@ var ReactMount = {
warning(
!containerHasNonRootReactChild,
'render(...): Replacing React-rendered children with a new root ' +
'component. If you intended to update the children of this node, ' +
'you should instead have the existing children update their state ' +
'and render the new components instead of calling ReactDOM.render.'
'component. If you intended to update the children of this node, ' +
'you should instead have the existing children update their state ' +
'and render the new components instead of calling ReactDOM.render.',
);
if (!containerHasReactMarkup || reactRootElement.nextSibling) {
@@ -507,8 +523,8 @@ var ReactMount = {
warning(
false,
'render(): Target node has markup rendered by React, but there ' +
'are unrelated nodes as well. This is most commonly caused by ' +
'white-space inserted around server-rendered markup.'
'are unrelated nodes as well. This is most commonly caused by ' +
'white-space inserted around server-rendered markup.',
);
break;
}
@@ -525,7 +541,7 @@ var ReactMount = {
nextWrappedElement,
container,
shouldReuseMarkup,
nextContext
nextContext,
)._renderedComponent.getPublicInstance();
if (callback) {
callback.call(component);
@@ -533,7 +549,6 @@ var ReactMount = {
return component;
},
/**
* Renders a React component into the DOM in the supplied `container`.
* See https://facebook.github.io/react/docs/top-level-api.html#reactdom.render
@@ -548,7 +563,12 @@ var ReactMount = {
* @return {ReactComponent} Component instance rendered in `container`.
*/
render: function(nextElement, container, callback) {
return ReactMount._renderSubtreeIntoContainer(null, nextElement, container, callback);
return ReactMount._renderSubtreeIntoContainer(
null,
nextElement,
container,
callback,
);
},
/**
@@ -567,23 +587,23 @@ var ReactMount = {
warning(
ReactCurrentOwner.current == null,
'unmountComponentAtNode(): Render methods should be a pure function ' +
'of props and state; triggering nested component updates from render ' +
'is not allowed. If necessary, trigger nested updates in ' +
'componentDidUpdate. Check the render method of %s.',
ReactCurrentOwner.current && ReactCurrentOwner.current.getName() ||
'ReactCompositeComponent'
'of props and state; triggering nested component updates from render ' +
'is not allowed. If necessary, trigger nested updates in ' +
'componentDidUpdate. Check the render method of %s.',
(ReactCurrentOwner.current && ReactCurrentOwner.current.getName()) ||
'ReactCompositeComponent',
);
invariant(
isValidContainer(container),
'unmountComponentAtNode(...): Target container is not a DOM element.'
'unmountComponentAtNode(...): Target container is not a DOM element.',
);
if (__DEV__) {
warning(
!nodeIsRenderedByOtherInstance(container),
'unmountComponentAtNode(): The node you\'re attempting to unmount ' +
'was rendered by another copy of React.'
"unmountComponentAtNode(): The node you're attempting to unmount " +
'was rendered by another copy of React.',
);
}
@@ -600,15 +620,13 @@ var ReactMount = {
if (__DEV__) {
warning(
!containerHasNonRootReactChild,
'unmountComponentAtNode(): The node you\'re attempting to unmount ' +
'was rendered by React and is not a top-level container. %s',
(
isContainerReactRoot ?
'You may have accidentally passed in a React root node instead ' +
'of its container.' :
'Instead, have the parent component update its state and ' +
'rerender in order to remove this component.'
)
"unmountComponentAtNode(): The node you're attempting to unmount " +
'was rendered by React and is not a top-level container. %s',
isContainerReactRoot
? 'You may have accidentally passed in a React root node instead ' +
'of its container.'
: 'Instead, have the parent component update its state and ' +
'rerender in order to remove this component.',
);
}
@@ -619,7 +637,7 @@ var ReactMount = {
unmountComponentFromNode,
prevComponent,
container,
false
false,
);
return true;
},
@@ -629,11 +647,11 @@ var ReactMount = {
container,
instance,
shouldReuseMarkup,
transaction
transaction,
) {
invariant(
isValidContainer(container),
'mountComponentIntoNode(...): Target container is not valid.'
'mountComponentIntoNode(...): Target container is not valid.',
);
if (shouldReuseMarkup) {
@@ -643,14 +661,14 @@ var ReactMount = {
return;
} else {
var checksum = rootElement.getAttribute(
ReactMarkupChecksum.CHECKSUM_ATTR_NAME
ReactMarkupChecksum.CHECKSUM_ATTR_NAME,
);
rootElement.removeAttribute(ReactMarkupChecksum.CHECKSUM_ATTR_NAME);
var rootMarkup = rootElement.outerHTML;
rootElement.setAttribute(
ReactMarkupChecksum.CHECKSUM_ATTR_NAME,
checksum
checksum,
);
var normalizedMarkup = markup;
@@ -668,41 +686,44 @@ var ReactMount = {
normalizer = document.createElement('iframe');
document.body.appendChild(normalizer);
normalizer.contentDocument.write(markup);
normalizedMarkup = normalizer.contentDocument.documentElement.outerHTML;
normalizedMarkup =
normalizer.contentDocument.documentElement.outerHTML;
document.body.removeChild(normalizer);
}
}
var diffIndex = firstDifferenceIndex(normalizedMarkup, rootMarkup);
var difference = ' (client) ' +
var difference =
' (client) ' +
normalizedMarkup.substring(diffIndex - 20, diffIndex + 20) +
'\n (server) ' + rootMarkup.substring(diffIndex - 20, diffIndex + 20);
'\n (server) ' +
rootMarkup.substring(diffIndex - 20, diffIndex + 20);
invariant(
container.nodeType !== DOC_NODE_TYPE,
'You\'re trying to render a component to the document using ' +
'server rendering but the checksum was invalid. This usually ' +
'means you rendered a different component type or props on ' +
'the client from the one on the server, or your render() ' +
'methods are impure. React cannot handle this case due to ' +
'cross-browser quirks by rendering at the document root. You ' +
'should look for environment dependent code in your components ' +
'and ensure the props are the same client and server side:\n%s',
difference
"You're trying to render a component to the document using " +
'server rendering but the checksum was invalid. This usually ' +
'means you rendered a different component type or props on ' +
'the client from the one on the server, or your render() ' +
'methods are impure. React cannot handle this case due to ' +
'cross-browser quirks by rendering at the document root. You ' +
'should look for environment dependent code in your components ' +
'and ensure the props are the same client and server side:\n%s',
difference,
);
if (__DEV__) {
warning(
false,
'React attempted to reuse markup in a container but the ' +
'checksum was invalid. This generally means that you are ' +
'using server rendering and the markup generated on the ' +
'server was not what the client was expecting. React injected ' +
'new markup to compensate which works but you have lost many ' +
'of the benefits of server rendering. Instead, figure out ' +
'why the markup being generated is different on the client ' +
'or server:\n%s',
difference
'checksum was invalid. This generally means that you are ' +
'using server rendering and the markup generated on the ' +
'server was not what the client was expecting. React injected ' +
'new markup to compensate which works but you have lost many ' +
'of the benefits of server rendering. Instead, figure out ' +
'why the markup being generated is different on the client ' +
'or server:\n%s',
difference,
);
}
}
@@ -710,10 +731,10 @@ var ReactMount = {
invariant(
container.nodeType !== DOC_NODE_TYPE,
'You\'re trying to render a component to the document but ' +
'you didn\'t use server rendering. We can\'t do this ' +
"You're trying to render a component to the document but " +
"you didn't use server rendering. We can't do this " +
'without using server rendering due to cross-browser quirks. ' +
'See ReactDOMServer.renderToString() for server rendering.'
'See ReactDOMServer.renderToString() for server rendering.',
);
if (transaction.useCreateElement) {
@@ -727,7 +748,9 @@ var ReactMount = {
}
if (__DEV__) {
var hostNode = ReactDOMComponentTree.getInstanceFromNode(container.firstChild);
var hostNode = ReactDOMComponentTree.getInstanceFromNode(
container.firstChild,
);
if (hostNode._debugID !== 0) {
ReactInstrumentation.debugTool.onHostOperation({
instanceID: hostNode._debugID,
@@ -19,7 +19,6 @@ var ReactInstrumentation = require('ReactInstrumentation');
var Transaction = require('Transaction');
var ReactUpdateQueue = require('ReactUpdateQueue');
/**
* Ensures that, when possible, the selection range (currently selected text
* input) is not disturbed by performing the transaction.
@@ -174,7 +173,6 @@ var Mixin = {
},
};
Object.assign(ReactReconcileTransaction.prototype, Transaction, Mixin);
PooledClass.addPoolingTo(ReactReconcileTransaction);
@@ -54,7 +54,6 @@ function getInternal(node) {
return ReactDOMComponentTree.getInstanceFromNode(node);
}
describe('ReactBrowserEventEmitter', () => {
beforeEach(() => {
jest.resetModuleRegistry();
@@ -69,11 +68,11 @@ describe('ReactBrowserEventEmitter', () => {
TapEventPlugin = require('TapEventPlugin');
ReactTestUtils.renderIntoDocument(
<div ref={(c) => GRANDPARENT = c}>
<div ref={(c) => PARENT = c}>
<div ref={(c) => CHILD = c} />
<div ref={c => (GRANDPARENT = c)}>
<div ref={c => (PARENT = c)}>
<div ref={c => (CHILD = c)} />
</div>
</div>
</div>,
);
idCallOrder = [];
@@ -108,34 +107,31 @@ describe('ReactBrowserEventEmitter', () => {
expect(LISTENER.mock.calls.length).toBe(1);
});
it(
'should not invoke handlers if ReactBrowserEventEmitter is disabled',
() => {
registerSimpleTestHandler();
ReactBrowserEventEmitter.setEnabled(false);
ReactTestUtils.SimulateNative.click(CHILD);
expect(LISTENER.mock.calls.length).toBe(0);
ReactBrowserEventEmitter.setEnabled(true);
ReactTestUtils.SimulateNative.click(CHILD);
expect(LISTENER.mock.calls.length).toBe(1);
}
);
it('should not invoke handlers if ReactBrowserEventEmitter is disabled', () => {
registerSimpleTestHandler();
ReactBrowserEventEmitter.setEnabled(false);
ReactTestUtils.SimulateNative.click(CHILD);
expect(LISTENER.mock.calls.length).toBe(0);
ReactBrowserEventEmitter.setEnabled(true);
ReactTestUtils.SimulateNative.click(CHILD);
expect(LISTENER.mock.calls.length).toBe(1);
});
it('should bubble simply', () => {
EventPluginHub.putListener(
getInternal(CHILD),
ON_CLICK_KEY,
recordID.bind(null, getInternal(CHILD))
recordID.bind(null, getInternal(CHILD)),
);
EventPluginHub.putListener(
getInternal(PARENT),
ON_CLICK_KEY,
recordID.bind(null, getInternal(PARENT))
recordID.bind(null, getInternal(PARENT)),
);
EventPluginHub.putListener(
getInternal(GRANDPARENT),
ON_CLICK_KEY,
recordID.bind(null, getInternal(GRANDPARENT))
recordID.bind(null, getInternal(GRANDPARENT)),
);
ReactTestUtils.Simulate.click(CHILD);
expect(idCallOrder.length).toBe(3);
@@ -148,20 +144,16 @@ describe('ReactBrowserEventEmitter', () => {
EventPluginHub.putListener(
getInternal(CHILD),
ON_CLICK_KEY,
recordID.bind(null, getInternal(CHILD))
);
EventPluginHub.putListener(
getInternal(PARENT),
ON_CLICK_KEY,
function() {
recordID(getInternal(PARENT));
throw new Error('Handler interrupted');
}
recordID.bind(null, getInternal(CHILD)),
);
EventPluginHub.putListener(getInternal(PARENT), ON_CLICK_KEY, function() {
recordID(getInternal(PARENT));
throw new Error('Handler interrupted');
});
EventPluginHub.putListener(
getInternal(GRANDPARENT),
ON_CLICK_KEY,
recordID.bind(null, getInternal(GRANDPARENT))
recordID.bind(null, getInternal(GRANDPARENT)),
);
expect(function() {
ReactTestUtils.Simulate.click(CHILD);
@@ -173,30 +165,24 @@ describe('ReactBrowserEventEmitter', () => {
});
it('should set currentTarget', () => {
EventPluginHub.putListener(
getInternal(CHILD),
ON_CLICK_KEY,
function(event) {
recordID(getInternal(CHILD));
expect(event.currentTarget).toBe(CHILD);
}
);
EventPluginHub.putListener(
getInternal(PARENT),
ON_CLICK_KEY,
function(event) {
recordID(getInternal(PARENT));
expect(event.currentTarget).toBe(PARENT);
}
);
EventPluginHub.putListener(
getInternal(GRANDPARENT),
ON_CLICK_KEY,
function(event) {
recordID(getInternal(GRANDPARENT));
expect(event.currentTarget).toBe(GRANDPARENT);
}
);
EventPluginHub.putListener(getInternal(CHILD), ON_CLICK_KEY, function(
event,
) {
recordID(getInternal(CHILD));
expect(event.currentTarget).toBe(CHILD);
});
EventPluginHub.putListener(getInternal(PARENT), ON_CLICK_KEY, function(
event,
) {
recordID(getInternal(PARENT));
expect(event.currentTarget).toBe(PARENT);
});
EventPluginHub.putListener(getInternal(GRANDPARENT), ON_CLICK_KEY, function(
event,
) {
recordID(getInternal(GRANDPARENT));
expect(event.currentTarget).toBe(GRANDPARENT);
});
ReactTestUtils.Simulate.click(CHILD);
expect(idCallOrder.length).toBe(3);
expect(idCallOrder[0]).toBe(getInternal(CHILD));
@@ -208,17 +194,17 @@ describe('ReactBrowserEventEmitter', () => {
EventPluginHub.putListener(
getInternal(CHILD),
ON_CLICK_KEY,
recordID.bind(null, getInternal(CHILD))
recordID.bind(null, getInternal(CHILD)),
);
EventPluginHub.putListener(
getInternal(PARENT),
ON_CLICK_KEY,
recordIDAndStopPropagation.bind(null, getInternal(PARENT))
recordIDAndStopPropagation.bind(null, getInternal(PARENT)),
);
EventPluginHub.putListener(
getInternal(GRANDPARENT),
ON_CLICK_KEY,
recordID.bind(null, getInternal(GRANDPARENT))
recordID.bind(null, getInternal(GRANDPARENT)),
);
ReactTestUtils.Simulate.click(CHILD);
expect(idCallOrder.length).toBe(2);
@@ -230,17 +216,17 @@ describe('ReactBrowserEventEmitter', () => {
EventPluginHub.putListener(
getInternal(CHILD),
ON_CLICK_KEY,
recordIDAndStopPropagation.bind(null, getInternal(CHILD))
recordIDAndStopPropagation.bind(null, getInternal(CHILD)),
);
EventPluginHub.putListener(
getInternal(PARENT),
ON_CLICK_KEY,
recordID.bind(null, getInternal(PARENT))
recordID.bind(null, getInternal(PARENT)),
);
EventPluginHub.putListener(
getInternal(GRANDPARENT),
ON_CLICK_KEY,
recordID.bind(null, getInternal(GRANDPARENT))
recordID.bind(null, getInternal(GRANDPARENT)),
);
ReactTestUtils.Simulate.click(CHILD);
expect(idCallOrder.length).toBe(1);
@@ -251,17 +237,17 @@ describe('ReactBrowserEventEmitter', () => {
EventPluginHub.putListener(
getInternal(CHILD),
ON_CLICK_KEY,
recordIDAndReturnFalse.bind(null, getInternal(CHILD))
recordIDAndReturnFalse.bind(null, getInternal(CHILD)),
);
EventPluginHub.putListener(
getInternal(PARENT),
ON_CLICK_KEY,
recordID.bind(null, getInternal(PARENT))
recordID.bind(null, getInternal(PARENT)),
);
EventPluginHub.putListener(
getInternal(GRANDPARENT),
ON_CLICK_KEY,
recordID.bind(null, getInternal(GRANDPARENT))
recordID.bind(null, getInternal(GRANDPARENT)),
);
spyOn(console, 'error');
ReactTestUtils.Simulate.click(CHILD);
@@ -289,12 +275,12 @@ describe('ReactBrowserEventEmitter', () => {
EventPluginHub.putListener(
getInternal(CHILD),
ON_CLICK_KEY,
handleChildClick
handleChildClick,
);
EventPluginHub.putListener(
getInternal(PARENT),
ON_CLICK_KEY,
handleParentClick
handleParentClick,
);
ReactTestUtils.Simulate.click(CHILD);
expect(handleParentClick.mock.calls.length).toBe(1);
@@ -306,13 +292,13 @@ describe('ReactBrowserEventEmitter', () => {
EventPluginHub.putListener(
getInternal(PARENT),
ON_CLICK_KEY,
handleParentClick
handleParentClick,
);
};
EventPluginHub.putListener(
getInternal(CHILD),
ON_CLICK_KEY,
handleChildClick
handleChildClick,
);
ReactTestUtils.Simulate.click(CHILD);
expect(handleParentClick.mock.calls.length).toBe(0);
@@ -322,7 +308,7 @@ describe('ReactBrowserEventEmitter', () => {
EventPluginHub.putListener(
getInternal(CHILD),
ON_MOUSE_ENTER_KEY,
recordID.bind(null, getInternal(CHILD))
recordID.bind(null, getInternal(CHILD)),
);
ReactTestUtils.Simulate.mouseEnter(CHILD);
expect(idCallOrder.length).toBe(1);
@@ -333,15 +319,15 @@ describe('ReactBrowserEventEmitter', () => {
EventPluginHub.putListener(
getInternal(CHILD),
ON_TOUCH_TAP_KEY,
recordID.bind(null, getInternal(CHILD))
recordID.bind(null, getInternal(CHILD)),
);
ReactTestUtils.SimulateNative.touchStart(
CHILD,
ReactTestUtils.nativeTouchData(0, 0)
ReactTestUtils.nativeTouchData(0, 0),
);
ReactTestUtils.SimulateNative.touchEnd(
CHILD,
ReactTestUtils.nativeTouchData(0, 0)
ReactTestUtils.nativeTouchData(0, 0),
);
expect(idCallOrder.length).toBe(1);
expect(idCallOrder[0]).toBe(getInternal(CHILD));
@@ -351,15 +337,15 @@ describe('ReactBrowserEventEmitter', () => {
EventPluginHub.putListener(
getInternal(CHILD),
ON_TOUCH_TAP_KEY,
recordID.bind(null, getInternal(CHILD))
recordID.bind(null, getInternal(CHILD)),
);
ReactTestUtils.SimulateNative.touchStart(
CHILD,
ReactTestUtils.nativeTouchData(0, 0)
ReactTestUtils.nativeTouchData(0, 0),
);
ReactTestUtils.SimulateNative.touchEnd(
CHILD,
ReactTestUtils.nativeTouchData(0, tapMoveThreshold - 1)
ReactTestUtils.nativeTouchData(0, tapMoveThreshold - 1),
);
expect(idCallOrder.length).toBe(1);
expect(idCallOrder[0]).toBe(getInternal(CHILD));
@@ -369,15 +355,15 @@ describe('ReactBrowserEventEmitter', () => {
EventPluginHub.putListener(
getInternal(CHILD),
ON_TOUCH_TAP_KEY,
recordID.bind(null, getInternal(CHILD))
recordID.bind(null, getInternal(CHILD)),
);
ReactTestUtils.SimulateNative.touchStart(
CHILD,
ReactTestUtils.nativeTouchData(0, 0)
ReactTestUtils.nativeTouchData(0, 0),
);
ReactTestUtils.SimulateNative.touchEnd(
CHILD,
ReactTestUtils.nativeTouchData(0, tapMoveThreshold + 1)
ReactTestUtils.nativeTouchData(0, tapMoveThreshold + 1),
);
expect(idCallOrder.length).toBe(0);
});
@@ -426,25 +412,25 @@ describe('ReactBrowserEventEmitter', () => {
EventPluginHub.putListener(
getInternal(CHILD),
ON_TOUCH_TAP_KEY,
recordID.bind(null, getInternal(CHILD))
recordID.bind(null, getInternal(CHILD)),
);
EventPluginHub.putListener(
getInternal(PARENT),
ON_TOUCH_TAP_KEY,
recordID.bind(null, getInternal(PARENT))
recordID.bind(null, getInternal(PARENT)),
);
EventPluginHub.putListener(
getInternal(GRANDPARENT),
ON_TOUCH_TAP_KEY,
recordID.bind(null, getInternal(GRANDPARENT))
recordID.bind(null, getInternal(GRANDPARENT)),
);
ReactTestUtils.SimulateNative.touchStart(
CHILD,
ReactTestUtils.nativeTouchData(0, 0)
ReactTestUtils.nativeTouchData(0, 0),
);
ReactTestUtils.SimulateNative.touchEnd(
CHILD,
ReactTestUtils.nativeTouchData(0, 0)
ReactTestUtils.nativeTouchData(0, 0),
);
expect(idCallOrder.length).toBe(3);
expect(idCallOrder[0]).toBe(getInternal(CHILD));
@@ -467,5 +453,4 @@ describe('ReactBrowserEventEmitter', () => {
document.createEvent = originalCreateEvent;
}
});
});
@@ -53,16 +53,14 @@ describe('ReactDOM', () => {
});
it('should allow children to be passed as an argument', () => {
var argDiv = ReactTestUtils.renderIntoDocument(
div(null, 'child')
);
var argDiv = ReactTestUtils.renderIntoDocument(div(null, 'child'));
var argNode = ReactDOM.findDOMNode(argDiv);
expect(argNode.innerHTML).toBe('child');
});
it('should overwrite props.children with children argument', () => {
var conflictDiv = ReactTestUtils.renderIntoDocument(
div({children: 'fakechild'}, 'child')
div({children: 'fakechild'}, 'child'),
);
var conflictNode = ReactDOM.findDOMNode(conflictDiv);
expect(conflictNode.innerHTML).toBe('child');
@@ -77,34 +75,34 @@ describe('ReactDOM', () => {
<div>
<div key="theDog" className="dog" />,
<div key="theBird" className="bird" />
</div>
</div>,
);
// Warm the cache with theDog
myDiv = ReactTestUtils.renderIntoDocument(
<div>
<div key="theDog" className="dogbeforedelete" />,
<div key="theBird" className="bird" />,
</div>
</div>,
);
// Remove theDog - this should purge the cache
myDiv = ReactTestUtils.renderIntoDocument(
<div>
<div key="theBird" className="bird" />,
</div>
</div>,
);
// Now, put theDog back. It's now a different DOM node.
myDiv = ReactTestUtils.renderIntoDocument(
<div>
<div key="theDog" className="dog" />,
<div key="theBird" className="bird" />,
</div>
</div>,
);
// Change the className of theDog. It will use the same element
myDiv = ReactTestUtils.renderIntoDocument(
<div>
<div key="theDog" className="bigdog" />,
<div key="theBird" className="bird" />,
</div>
</div>,
);
var root = ReactDOM.findDOMNode(myDiv);
var dog = root.childNodes[0];
@@ -135,15 +133,15 @@ describe('ReactDOM', () => {
var myDiv = document.createElement('div');
expect(() => ReactDOM.render(<A />, myDiv, 'no')).toThrowError(
'ReactDOM.render(...): Expected the last optional `callback` argument ' +
'to be a function. Instead received: string.'
'to be a function. Instead received: string.',
);
expect(() => ReactDOM.render(<A />, myDiv, {})).toThrowError(
'ReactDOM.render(...): Expected the last optional `callback` argument ' +
'to be a function. Instead received: Object.'
'to be a function. Instead received: Object.',
);
expect(() => ReactDOM.render(<A />, myDiv, new Foo())).toThrowError(
'ReactDOM.render(...): Expected the last optional `callback` argument ' +
'to be a function. Instead received: Foo (keys: a, b).'
'to be a function. Instead received: Foo (keys: a, b).',
);
});
@@ -166,15 +164,15 @@ describe('ReactDOM', () => {
expect(() => ReactDOM.render(<A />, myDiv, 'no')).toThrowError(
'ReactDOM.render(...): Expected the last optional `callback` argument ' +
'to be a function. Instead received: string.'
'to be a function. Instead received: string.',
);
expect(() => ReactDOM.render(<A />, myDiv, {})).toThrowError(
'ReactDOM.render(...): Expected the last optional `callback` argument ' +
'to be a function. Instead received: Object.'
'to be a function. Instead received: Object.',
);
expect(() => ReactDOM.render(<A />, myDiv, new Foo())).toThrowError(
'ReactDOM.render(...): Expected the last optional `callback` argument ' +
'to be a function. Instead received: Foo (keys: a, b).'
'to be a function. Instead received: Foo (keys: a, b).',
);
});
});
@@ -88,7 +88,7 @@ describe('ReactDOMComponentTree', () => {
function renderAndGetClosest(sel) {
return ReactDOMComponentTree.getClosestInstanceFromNode(
renderAndQuery(sel)
renderAndQuery(sel),
);
}
@@ -101,11 +101,12 @@ describe('ReactDOMComponentTree', () => {
// This one's a text component!
var root = renderAndQuery(null);
var inst = ReactDOMComponentTree.getInstanceFromNode(root.children[0].childNodes[2]);
var inst = ReactDOMComponentTree.getInstanceFromNode(
root.children[0].childNodes[2],
);
expect(inst._stringText).toBe('goodbye.');
expect(renderAndGetClosest('b')._currentElement.type).toBe('main');
expect(renderAndGetClosest('img')._currentElement.type).toBe('main');
});
});
@@ -23,13 +23,15 @@ describe('ReactDOMIDOperations', () => {
var html = '\n \t <span> \n testContent \t </span> \n \t';
ReactDOMIDOperations.dangerouslyProcessChildrenUpdates(
stubInstance,
[{
type: 'SET_MARKUP',
content: html,
fromIndex: null,
toIndex: null,
}],
[]
[
{
type: 'SET_MARKUP',
content: html,
fromIndex: null,
toIndex: null,
},
],
[],
);
expect(stubNode.innerHTML).toBe(html);
@@ -15,7 +15,6 @@ var React;
var ReactDOMServer;
describe('ReactDOMSVG', () => {
beforeEach(() => {
React = require('React');
ReactDOMServer = require('ReactDOMServer');
@@ -25,9 +24,8 @@ describe('ReactDOMSVG', () => {
var markup = ReactDOMServer.renderToString(
<svg>
<image xlinkHref="http://i.imgur.com/w7GCRPb.png" />
</svg>
</svg>,
);
expect(markup).toContain('xlink:href="http://i.imgur.com/w7GCRPb.png"');
});
});
@@ -113,7 +113,11 @@ describe('ReactDOMTreeTraversal', () => {
var target = null;
var expectedAggregation = [];
ReactDOMTreeTraversal.traverseEnterLeave(
target, target, argAggregator, ARG, ARG2
target,
target,
argAggregator,
ARG,
ARG2,
);
expect(aggregatedArgs).toEqual(expectedAggregation);
});
@@ -124,7 +128,11 @@ describe('ReactDOMTreeTraversal', () => {
var enter = getInst(parent.refs.P_P1_C1.refs.DIV_1);
var expectedAggregation = [];
ReactDOMTreeTraversal.traverseEnterLeave(
leave, enter, argAggregator, ARG, ARG2
leave,
enter,
argAggregator,
ARG,
ARG2,
);
expect(aggregatedArgs).toEqual(expectedAggregation);
});
@@ -139,7 +147,11 @@ describe('ReactDOMTreeTraversal', () => {
{node: parent.refs.P_P1_C1.refs.DIV_2, phase: 'captured', arg: ARG2},
];
ReactDOMTreeTraversal.traverseEnterLeave(
leave, enter, argAggregator, ARG, ARG2
leave,
enter,
argAggregator,
ARG,
ARG2,
);
expect(aggregatedArgs).toEqual(expectedAggregation);
});
@@ -152,7 +164,11 @@ describe('ReactDOMTreeTraversal', () => {
{node: parent.refs.P_P1_C1.refs.DIV_1, phase: 'bubbled', arg: ARG},
];
ReactDOMTreeTraversal.traverseEnterLeave(
leave, enter, argAggregator, ARG, ARG2
leave,
enter,
argAggregator,
ARG,
ARG2,
);
expect(aggregatedArgs).toEqual(expectedAggregation);
});
@@ -167,7 +183,11 @@ describe('ReactDOMTreeTraversal', () => {
{node: parent.refs.P_P1_C1.refs.DIV, phase: 'captured', arg: ARG2},
];
ReactDOMTreeTraversal.traverseEnterLeave(
leave, enter, argAggregator, ARG, ARG2
leave,
enter,
argAggregator,
ARG,
ARG2,
);
expect(aggregatedArgs).toEqual(expectedAggregation);
});
@@ -180,7 +200,11 @@ describe('ReactDOMTreeTraversal', () => {
{node: parent.refs.P, phase: 'captured', arg: ARG2},
];
ReactDOMTreeTraversal.traverseEnterLeave(
leave, enter, argAggregator, ARG, ARG2
leave,
enter,
argAggregator,
ARG,
ARG2,
);
expect(aggregatedArgs).toEqual(expectedAggregation);
});
@@ -195,7 +219,11 @@ describe('ReactDOMTreeTraversal', () => {
{node: parent.refs.P, phase: 'bubbled', arg: ARG},
];
ReactDOMTreeTraversal.traverseEnterLeave(
leave, enter, argAggregator, ARG, ARG2
leave,
enter,
argAggregator,
ARG,
ARG2,
);
expect(aggregatedArgs).toEqual(expectedAggregation);
});
@@ -210,7 +238,11 @@ describe('ReactDOMTreeTraversal', () => {
{node: parent.refs.P, phase: 'bubbled', arg: ARG},
];
ReactDOMTreeTraversal.traverseEnterLeave(
leave, enter, argAggregator, ARG, ARG2
leave,
enter,
argAggregator,
ARG,
ARG2,
);
expect(aggregatedArgs).toEqual(expectedAggregation);
});
@@ -221,7 +253,8 @@ describe('ReactDOMTreeTraversal', () => {
var parent = renderParentIntoDocument();
var ancestors = [
// Common ancestor with self is self.
{one: parent.refs.P_P1_C1.refs.DIV_1,
{
one: parent.refs.P_P1_C1.refs.DIV_1,
two: parent.refs.P_P1_C1.refs.DIV_1,
com: parent.refs.P_P1_C1.refs.DIV_1,
},
@@ -263,11 +296,10 @@ describe('ReactDOMTreeTraversal', () => {
var plan = ancestors[i];
var firstCommon = ReactDOMTreeTraversal.getLowestCommonAncestor(
getInst(plan.one),
getInst(plan.two)
getInst(plan.two),
);
expect(firstCommon).toBe(getInst(plan.com));
}
});
});
});
@@ -32,7 +32,7 @@ describe('ReactEventIndependence', () => {
dangerouslySetInnerHTML={{
__html: '<button data-reactid=".z">click me</div>',
}}
/>
/>,
);
ReactTestUtils.SimulateNative.click(div.firstChild);
expect(clicks).toBe(1);
@@ -44,7 +44,7 @@ describe('ReactEventIndependence', () => {
outer.setAttribute('data-reactid', '.z');
var inner = ReactDOM.render(
<button onClick={() => clicks++}>click me</button>,
outer
outer,
);
ReactTestUtils.SimulateNative.click(inner);
expect(clicks).toBe(1);
@@ -55,7 +55,7 @@ describe('ReactEventIndependence', () => {
var container = document.createElement('div');
var button = ReactDOM.render(
<button onClick={() => clicks++}>click me</button>,
container
container,
);
// Now we unmount the component, as if caused by a non-React event handler
@@ -66,5 +66,4 @@ describe('ReactEventIndependence', () => {
// Since the tree is unmounted, we don't dispatch the click event.
expect(clicks).toBe(0);
});
});
@@ -11,7 +11,6 @@
'use strict';
var EVENT_TARGET_PARAM = 1;
describe('ReactEventListener', () => {
@@ -38,19 +37,16 @@ describe('ReactEventListener', () => {
var otherNode = document.createElement('h1');
var component = ReactDOM.render(<div />, document.createElement('div'));
expect(handleTopLevel.mock.calls.length).toBe(0);
ReactEventListener.dispatchEvent(
'topMouseOut',
{
type: 'mouseout',
fromElement: otherNode,
target: otherNode,
srcElement: otherNode,
toElement: ReactDOM.findDOMNode(component),
relatedTarget: ReactDOM.findDOMNode(component),
view: window,
path: [otherNode, otherNode],
},
);
ReactEventListener.dispatchEvent('topMouseOut', {
type: 'mouseout',
fromElement: otherNode,
target: otherNode,
srcElement: otherNode,
toElement: ReactDOM.findDOMNode(component),
relatedTarget: ReactDOM.findDOMNode(component),
view: window,
path: [otherNode, otherNode],
});
expect(handleTopLevel.mock.calls.length).toBe(1);
});
@@ -61,8 +57,7 @@ describe('ReactEventListener', () => {
var parentContainer = document.createElement('div');
var parentControl = <div>Parent</div>;
childControl = ReactDOM.render(childControl, childContainer);
parentControl =
ReactDOM.render(parentControl, parentContainer);
parentControl = ReactDOM.render(parentControl, parentContainer);
ReactDOM.findDOMNode(parentControl).appendChild(childContainer);
var callback = ReactEventListener.dispatchEvent.bind(null, 'test');
@@ -72,10 +67,12 @@ describe('ReactEventListener', () => {
var calls = handleTopLevel.mock.calls;
expect(calls.length).toBe(2);
expect(calls[0][EVENT_TARGET_PARAM])
.toBe(ReactDOMComponentTree.getInstanceFromNode(childControl));
expect(calls[1][EVENT_TARGET_PARAM])
.toBe(ReactDOMComponentTree.getInstanceFromNode(parentControl));
expect(calls[0][EVENT_TARGET_PARAM]).toBe(
ReactDOMComponentTree.getInstanceFromNode(childControl),
);
expect(calls[1][EVENT_TARGET_PARAM]).toBe(
ReactDOMComponentTree.getInstanceFromNode(parentControl),
);
});
it('should propagate events two levels down', () => {
@@ -86,10 +83,11 @@ describe('ReactEventListener', () => {
var grandParentContainer = document.createElement('div');
var grandParentControl = <div>Parent</div>;
childControl = ReactDOM.render(childControl, childContainer);
parentControl =
ReactDOM.render(parentControl, parentContainer);
grandParentControl =
ReactDOM.render(grandParentControl, grandParentContainer);
parentControl = ReactDOM.render(parentControl, parentContainer);
grandParentControl = ReactDOM.render(
grandParentControl,
grandParentContainer,
);
ReactDOM.findDOMNode(parentControl).appendChild(childContainer);
ReactDOM.findDOMNode(grandParentControl).appendChild(parentContainer);
@@ -100,12 +98,15 @@ describe('ReactEventListener', () => {
var calls = handleTopLevel.mock.calls;
expect(calls.length).toBe(3);
expect(calls[0][EVENT_TARGET_PARAM])
.toBe(ReactDOMComponentTree.getInstanceFromNode(childControl));
expect(calls[1][EVENT_TARGET_PARAM])
.toBe(ReactDOMComponentTree.getInstanceFromNode(parentControl));
expect(calls[2][EVENT_TARGET_PARAM])
.toBe(ReactDOMComponentTree.getInstanceFromNode(grandParentControl));
expect(calls[0][EVENT_TARGET_PARAM]).toBe(
ReactDOMComponentTree.getInstanceFromNode(childControl),
);
expect(calls[1][EVENT_TARGET_PARAM]).toBe(
ReactDOMComponentTree.getInstanceFromNode(parentControl),
);
expect(calls[2][EVENT_TARGET_PARAM]).toBe(
ReactDOMComponentTree.getInstanceFromNode(grandParentControl),
);
});
it('should not get confused by disappearing elements', () => {
@@ -114,8 +115,7 @@ describe('ReactEventListener', () => {
var parentContainer = document.createElement('div');
var parentControl = <div>Parent</div>;
childControl = ReactDOM.render(childControl, childContainer);
parentControl =
ReactDOM.render(parentControl, parentContainer);
parentControl = ReactDOM.render(parentControl, parentContainer);
ReactDOM.findDOMNode(parentControl).appendChild(childContainer);
// ReactBrowserEventEmitter.handleTopLevel might remove the
@@ -123,13 +123,16 @@ describe('ReactEventListener', () => {
// node when the first event handlers are called; we'll still
// expect to receive a second call for the parent control.
var childNode = ReactDOM.findDOMNode(childControl);
handleTopLevel.mockImplementation(
function(topLevelType, topLevelTarget, topLevelTargetID, nativeEvent) {
if (topLevelTarget === childNode) {
ReactDOM.unmountComponentAtNode(childContainer);
}
handleTopLevel.mockImplementation(function(
topLevelType,
topLevelTarget,
topLevelTargetID,
nativeEvent,
) {
if (topLevelTarget === childNode) {
ReactDOM.unmountComponentAtNode(childContainer);
}
);
});
var callback = ReactEventListener.dispatchEvent.bind(null, 'test');
callback({
@@ -138,41 +141,42 @@ describe('ReactEventListener', () => {
var calls = handleTopLevel.mock.calls;
expect(calls.length).toBe(2);
expect(calls[0][EVENT_TARGET_PARAM])
.toBe(ReactDOMComponentTree.getInstanceFromNode(childNode));
expect(calls[1][EVENT_TARGET_PARAM])
.toBe(ReactDOMComponentTree.getInstanceFromNode(parentControl));
expect(calls[0][EVENT_TARGET_PARAM]).toBe(
ReactDOMComponentTree.getInstanceFromNode(childNode),
);
expect(calls[1][EVENT_TARGET_PARAM]).toBe(
ReactDOMComponentTree.getInstanceFromNode(parentControl),
);
});
it('should batch between handlers from different roots', () => {
var childContainer = document.createElement('div');
var parentContainer = document.createElement('div');
var childControl = ReactDOM.render(
<div>Child</div>,
childContainer
);
var parentControl = ReactDOM.render(
<div>Parent</div>,
parentContainer
);
var childControl = ReactDOM.render(<div>Child</div>, childContainer);
var parentControl = ReactDOM.render(<div>Parent</div>, parentContainer);
ReactDOM.findDOMNode(parentControl).appendChild(childContainer);
// Suppose an event handler in each root enqueues an update to the
// childControl element -- the two updates should get batched together.
var childNode = ReactDOM.findDOMNode(childControl);
handleTopLevel.mockImplementation(
function(topLevelType, topLevelTarget, topLevelTargetID, nativeEvent) {
ReactDOM.render(
<div>{topLevelTarget === childNode ? '1' : '2'}</div>,
childContainer
);
// Since we're batching, neither update should yet have gone through.
expect(childNode.textContent).toBe('Child');
}
);
handleTopLevel.mockImplementation(function(
topLevelType,
topLevelTarget,
topLevelTargetID,
nativeEvent,
) {
ReactDOM.render(
<div>{topLevelTarget === childNode ? '1' : '2'}</div>,
childContainer,
);
// Since we're batching, neither update should yet have gone through.
expect(childNode.textContent).toBe('Child');
});
var callback =
ReactEventListener.dispatchEvent.bind(ReactEventListener, 'test');
var callback = ReactEventListener.dispatchEvent.bind(
ReactEventListener,
'test',
);
callback({
target: childNode,
});
@@ -204,7 +208,8 @@ describe('ReactEventListener', () => {
var calls = handleTopLevel.mock.calls;
expect(calls.length).toBe(1);
expect(calls[0][EVENT_TARGET_PARAM])
.toBe(ReactDOMComponentTree.getInstanceFromNode(instance.getInner()));
expect(calls[0][EVENT_TARGET_PARAM]).toBe(
ReactDOMComponentTree.getInstanceFromNode(instance.getInner()),
);
});
});
@@ -45,7 +45,7 @@ describe('ReactMount', () => {
expect(function() {
ReactDOM.unmountComponentAtNode(nodeArray);
}).toThrowError(
'unmountComponentAtNode(...): Target container is not a DOM element.'
'unmountComponentAtNode(...): Target container is not a DOM element.',
);
});
});
@@ -55,7 +55,7 @@ describe('ReactMount', () => {
ReactTestUtils.renderIntoDocument('div');
}).toThrowError(
'ReactDOM.render(): Invalid component element. Instead of passing a ' +
'string like \'div\', pass React.createElement(\'div\') or <div />.'
"string like 'div', pass React.createElement('div') or <div />.",
);
});
@@ -70,7 +70,7 @@ describe('ReactMount', () => {
ReactTestUtils.renderIntoDocument(Component);
}).toThrowError(
'ReactDOM.render(): Invalid component element. Instead of passing a ' +
'class like Foo, pass React.createElement(Foo) or <Foo />.'
'class like Foo, pass React.createElement(Foo) or <Foo />.',
);
});
@@ -160,25 +160,26 @@ describe('ReactMount', () => {
expect(console.error.calls.count()).toBe(1);
expect(console.error.calls.argsFor(0)[0]).toContain(
'Rendering components directly into document.body is discouraged'
'Rendering components directly into document.body is discouraged',
);
});
it('should account for escaping on a checksum mismatch', () => {
var div = document.createElement('div');
var markup = ReactDOMServer.renderToString(
<div>This markup contains an nbsp entity: &nbsp; server text</div>);
<div>This markup contains an nbsp entity: &nbsp; server text</div>,
);
div.innerHTML = markup;
spyOn(console, 'error');
ReactDOM.render(
<div>This markup contains an nbsp entity: &nbsp; client text</div>,
div
div,
);
expect(console.error.calls.count()).toBe(1);
expect(console.error.calls.argsFor(0)[0]).toContain(
' (client) nbsp entity: &nbsp; client text</div>\n' +
' (server) nbsp entity: &nbsp; server text</div>'
' (server) nbsp entity: &nbsp; server text</div>',
);
});
@@ -223,9 +224,9 @@ describe('ReactMount', () => {
expect(console.error.calls.count()).toBe(1);
expect(console.error.calls.argsFor(0)[0]).toBe(
'Warning: render(...): Replacing React-rendered children with a new ' +
'root component. If you intended to update the children of this node, ' +
'you should instead have the existing children update their state and ' +
'render the new components instead of calling ReactDOM.render.'
'root component. If you intended to update the children of this node, ' +
'you should instead have the existing children update their state and ' +
'render the new components instead of calling ReactDOM.render.',
);
});
@@ -248,8 +249,8 @@ describe('ReactMount', () => {
ReactDOMOther.unmountComponentAtNode(container);
expect(console.error.calls.count()).toBe(1);
expect(console.error.calls.argsFor(0)[0]).toBe(
'Warning: unmountComponentAtNode(): The node you\'re attempting to unmount ' +
'was rendered by another copy of React.'
"Warning: unmountComponentAtNode(): The node you're attempting to unmount " +
'was rendered by another copy of React.',
);
// Don't throw a warning if the correct React copy unmounts the node
@@ -43,10 +43,11 @@ describe('ReactMount', () => {
it('should warn when unmounting a non-container root node', () => {
var mainContainerDiv = document.createElement('div');
var component =
var component = (
<div>
<div />
</div>;
</div>
);
ReactDOM.render(component, mainContainerDiv);
// Test that unmounting at a root node gives a helpful warning
@@ -55,22 +56,23 @@ describe('ReactMount', () => {
ReactDOM.unmountComponentAtNode(rootDiv);
expect(console.error.calls.count()).toBe(1);
expect(console.error.calls.argsFor(0)[0]).toBe(
'Warning: unmountComponentAtNode(): The node you\'re attempting to ' +
'unmount was rendered by React and is not a top-level container. You ' +
'may have accidentally passed in a React root node instead of its ' +
'container.'
"Warning: unmountComponentAtNode(): The node you're attempting to " +
'unmount was rendered by React and is not a top-level container. You ' +
'may have accidentally passed in a React root node instead of its ' +
'container.',
);
});
it('should warn when unmounting a non-container, non-root node', () => {
var mainContainerDiv = document.createElement('div');
var component =
var component = (
<div>
<div>
<div />
</div>
</div>;
</div>
);
ReactDOM.render(component, mainContainerDiv);
// Test that unmounting at a non-root node gives a different warning
@@ -79,10 +81,10 @@ describe('ReactMount', () => {
ReactDOM.unmountComponentAtNode(nonRootDiv);
expect(console.error.calls.count()).toBe(1);
expect(console.error.calls.argsFor(0)[0]).toBe(
'Warning: unmountComponentAtNode(): The node you\'re attempting to ' +
'unmount was rendered by React and is not a top-level container. ' +
'Instead, have the parent component update its state and rerender in ' +
'order to remove this component.'
"Warning: unmountComponentAtNode(): The node you're attempting to " +
'unmount was rendered by React and is not a top-level container. ' +
'Instead, have the parent component update its state and rerender in ' +
'order to remove this component.',
);
});
});
@@ -166,7 +166,7 @@ describe('rendering React components at document', () => {
}
var markup = ReactDOMServer.renderToString(
<Component text="Hello world" />
<Component text="Hello world" />,
);
testDocument = getTestDocument(markup);
@@ -194,7 +194,7 @@ describe('rendering React components at document', () => {
}
var markup = ReactDOMServer.renderToString(
<Component text="Goodbye world" />
<Component text="Goodbye world" />,
);
testDocument = getTestDocument(markup);
@@ -202,16 +202,16 @@ describe('rendering React components at document', () => {
// Notice the text is different!
ReactDOM.render(<Component text="Hello world" />, testDocument);
}).toThrowError(
'You\'re trying to render a component to the document using ' +
'server rendering but the checksum was invalid. This usually ' +
'means you rendered a different component type or props on ' +
'the client from the one on the server, or your render() methods ' +
'are impure. React cannot handle this case due to cross-browser ' +
'quirks by rendering at the document root. You should look for ' +
'environment dependent code in your components and ensure ' +
'the props are the same client and server side:\n' +
' (client) dy data-reactid="4">Hello world</body></\n' +
' (server) dy data-reactid="4">Goodbye world</body>'
"You're trying to render a component to the document using " +
'server rendering but the checksum was invalid. This usually ' +
'means you rendered a different component type or props on ' +
'the client from the one on the server, or your render() methods ' +
'are impure. React cannot handle this case due to cross-browser ' +
'quirks by rendering at the document root. You should look for ' +
'environment dependent code in your components and ensure ' +
'the props are the same client and server side:\n' +
' (client) dy data-reactid="4">Hello world</body></\n' +
' (server) dy data-reactid="4">Goodbye world</body>',
);
});
@@ -238,15 +238,15 @@ describe('rendering React components at document', () => {
expect(function() {
ReactDOM.render(<Component />, container);
}).toThrowError(
'You\'re trying to render a component to the document but you didn\'t ' +
'use server rendering. We can\'t do this without using server ' +
'rendering due to cross-browser quirks. See ' +
'ReactDOMServer.renderToString() for server rendering.'
"You're trying to render a component to the document but you didn't " +
"use server rendering. We can't do this without using server " +
'rendering due to cross-browser quirks. See ' +
'ReactDOMServer.renderToString() for server rendering.',
);
});
it('supports findDOMNode on full-page components', () => {
var tree =
var tree = (
<html>
<head>
<title>Hello World</title>
@@ -254,7 +254,8 @@ describe('rendering React components at document', () => {
<body>
Hello world
</body>
</html>;
</html>
);
var markup = ReactDOMServer.renderToString(tree);
testDocument = getTestDocument(markup);
@@ -38,7 +38,7 @@ describe('findDOMNode', () => {
expect(function() {
ReactDOM.findDOMNode({foo: 'bar'});
}).toThrowError(
'Element appears to be neither ReactComponent nor DOMNode (keys: foo)'
'Element appears to be neither ReactComponent nor DOMNode (keys: foo)',
);
});
@@ -54,7 +54,7 @@ describe('findDOMNode', () => {
ReactDOM.unmountComponentAtNode(container);
expect(() => ReactDOM.findDOMNode(inst)).toThrowError(
'findDOMNode was called on an unmounted component.'
'findDOMNode was called on an unmounted component.',
);
});
@@ -65,11 +65,10 @@ describe('findDOMNode', () => {
}
render() {
return <div/>;
return <div />;
}
}
expect(() => ReactTestUtils.renderIntoDocument(<Bar/>)).not.toThrow();
expect(() => ReactTestUtils.renderIntoDocument(<Bar />)).not.toThrow();
});
});
@@ -15,22 +15,107 @@ var validateDOMNesting;
// https://html.spec.whatwg.org/multipage/syntax.html#special
var specialTags = [
'address', 'applet', 'area', 'article', 'aside', 'base', 'basefont',
'bgsound', 'blockquote', 'body', 'br', 'button', 'caption', 'center', 'col',
'colgroup', 'dd', 'details', 'dir', 'div', 'dl', 'dt', 'embed', 'fieldset',
'figcaption', 'figure', 'footer', 'form', 'frame', 'frameset', 'h1', 'h2',
'h3', 'h4', 'h5', 'h6', 'head', 'header', 'hgroup', 'hr', 'html', 'iframe',
'img', 'input', 'isindex', 'li', 'link', 'listing', 'main', 'marquee', 'menu',
'menuitem', 'meta', 'nav', 'noembed', 'noframes', 'noscript', 'object', 'ol',
'p', 'param', 'plaintext', 'pre', 'script', 'section', 'select', 'source',
'style', 'summary', 'table', 'tbody', 'td', 'template', 'textarea', 'tfoot',
'th', 'thead', 'title', 'tr', 'track', 'ul', 'wbr', 'xmp',
'address',
'applet',
'area',
'article',
'aside',
'base',
'basefont',
'bgsound',
'blockquote',
'body',
'br',
'button',
'caption',
'center',
'col',
'colgroup',
'dd',
'details',
'dir',
'div',
'dl',
'dt',
'embed',
'fieldset',
'figcaption',
'figure',
'footer',
'form',
'frame',
'frameset',
'h1',
'h2',
'h3',
'h4',
'h5',
'h6',
'head',
'header',
'hgroup',
'hr',
'html',
'iframe',
'img',
'input',
'isindex',
'li',
'link',
'listing',
'main',
'marquee',
'menu',
'menuitem',
'meta',
'nav',
'noembed',
'noframes',
'noscript',
'object',
'ol',
'p',
'param',
'plaintext',
'pre',
'script',
'section',
'select',
'source',
'style',
'summary',
'table',
'tbody',
'td',
'template',
'textarea',
'tfoot',
'th',
'thead',
'title',
'tr',
'track',
'ul',
'wbr',
'xmp',
];
// https://html.spec.whatwg.org/multipage/syntax.html#formatting
var formattingTags = [
'a', 'b', 'big', 'code', 'em', 'font', 'i', 'nobr', 's', 'small', 'strike',
'strong', 'tt', 'u',
'a',
'b',
'big',
'code',
'em',
'font',
'i',
'nobr',
's',
'small',
'strike',
'strong',
'tt',
'u',
];
function isTagStackValid(stack) {
@@ -39,8 +124,11 @@ function isTagStackValid(stack) {
if (!validateDOMNesting.isTagValidInContext(stack[i], ancestorInfo)) {
return false;
}
ancestorInfo =
validateDOMNesting.updatedAncestorInfo(ancestorInfo, stack[i], null);
ancestorInfo = validateDOMNesting.updatedAncestorInfo(
ancestorInfo,
stack[i],
null,
);
}
return true;
}
@@ -17,15 +17,13 @@ var FallbackCompositionState = require('FallbackCompositionState');
var SyntheticCompositionEvent = require('SyntheticCompositionEvent');
var SyntheticInputEvent = require('SyntheticInputEvent');
import type { TopLevelTypes } from 'EventConstants';
import type {TopLevelTypes} from 'EventConstants';
var END_KEYCODES = [9, 13, 27, 32]; // Tab, Return, Esc, Space
var START_KEYCODE = 229;
var canUseCompositionEvent = (
ExecutionEnvironment.canUseDOM &&
'CompositionEvent' in window
);
var canUseCompositionEvent =
ExecutionEnvironment.canUseDOM && 'CompositionEvent' in window;
var documentMode = null;
if (ExecutionEnvironment.canUseDOM && 'documentMode' in document) {
@@ -35,23 +33,19 @@ if (ExecutionEnvironment.canUseDOM && 'documentMode' in document) {
// Webkit offers a very useful `textInput` event that can be used to
// directly represent `beforeInput`. The IE `textinput` event is not as
// useful, so we don't use it.
var canUseTextInputEvent = (
var canUseTextInputEvent =
ExecutionEnvironment.canUseDOM &&
'TextEvent' in window &&
!documentMode &&
!isPresto()
);
!isPresto();
// In IE9+, we have access to composition events, but the data supplied
// by the native compositionend event may be incorrect. Japanese ideographic
// spaces, for instance (\u3000) are not recorded correctly.
var useFallbackCompositionData = (
var useFallbackCompositionData =
ExecutionEnvironment.canUseDOM &&
(
!canUseCompositionEvent ||
(documentMode && documentMode > 8 && documentMode <= 11)
)
);
(!canUseCompositionEvent ||
(documentMode && documentMode > 8 && documentMode <= 11));
/**
* Opera <= 12 includes TextEvent in window, but does not fire
@@ -143,7 +137,6 @@ function isKeypressCommand(nativeEvent) {
);
}
/**
* Translate native top level events into event types.
*
@@ -170,10 +163,7 @@ function getCompositionEventType(topLevelType) {
* @return {boolean}
*/
function isFallbackCompositionStart(topLevelType, nativeEvent) {
return (
topLevelType === 'topKeyDown' &&
nativeEvent.keyCode === START_KEYCODE
);
return topLevelType === 'topKeyDown' && nativeEvent.keyCode === START_KEYCODE;
}
/**
@@ -187,11 +177,11 @@ function isFallbackCompositionEnd(topLevelType, nativeEvent) {
switch (topLevelType) {
case 'topKeyUp':
// Command keys insert or clear IME input.
return (END_KEYCODES.indexOf(nativeEvent.keyCode) !== -1);
return END_KEYCODES.indexOf(nativeEvent.keyCode) !== -1;
case 'topKeyDown':
// Expect IME keyCode on each keydown. If we get any other
// code we must have exited earlier.
return (nativeEvent.keyCode !== START_KEYCODE);
return nativeEvent.keyCode !== START_KEYCODE;
case 'topKeyPress':
case 'topMouseDown':
case 'topBlur':
@@ -229,7 +219,7 @@ function extractCompositionEvent(
topLevelType,
targetInst,
nativeEvent,
nativeEventTarget
nativeEventTarget,
) {
var eventType;
var fallbackData;
@@ -252,8 +242,9 @@ function extractCompositionEvent(
// The current composition is stored statically and must not be
// overwritten while composition continues.
if (!currentComposition && eventType === eventTypes.compositionStart) {
currentComposition =
FallbackCompositionState.getPooled(nativeEventTarget);
currentComposition = FallbackCompositionState.getPooled(
nativeEventTarget,
);
} else if (eventType === eventTypes.compositionEnd) {
if (currentComposition) {
fallbackData = currentComposition.getData();
@@ -265,7 +256,7 @@ function extractCompositionEvent(
eventType,
targetInst,
nativeEvent,
nativeEventTarget
nativeEventTarget,
);
if (fallbackData) {
@@ -348,9 +339,11 @@ function getFallbackBeforeInputChars(topLevelType: TopLevelTypes, nativeEvent) {
// If composition event is available, we extract a string only at
// compositionevent, otherwise extract it at fallback events.
if (currentComposition) {
if (topLevelType === 'topCompositionEnd'
|| (!canUseCompositionEvent
&& isFallbackCompositionEnd(topLevelType, nativeEvent))) {
if (
topLevelType === 'topCompositionEnd' ||
(!canUseCompositionEvent &&
isFallbackCompositionEnd(topLevelType, nativeEvent))
) {
var chars = currentComposition.getData();
FallbackCompositionState.release(currentComposition);
currentComposition = null;
@@ -402,7 +395,7 @@ function extractBeforeInputEvent(
topLevelType,
targetInst,
nativeEvent,
nativeEventTarget
nativeEventTarget,
) {
var chars;
@@ -422,7 +415,7 @@ function extractBeforeInputEvent(
eventTypes.beforeInput,
targetInst,
nativeEvent,
nativeEventTarget
nativeEventTarget,
);
event.data = chars;
@@ -449,27 +442,26 @@ function extractBeforeInputEvent(
* `composition` event types.
*/
var BeforeInputEventPlugin = {
eventTypes: eventTypes,
extractEvents: function(
topLevelType,
targetInst,
nativeEvent,
nativeEventTarget
nativeEventTarget,
) {
return [
extractCompositionEvent(
topLevelType,
targetInst,
nativeEvent,
nativeEventTarget
nativeEventTarget,
),
extractBeforeInputEvent(
topLevelType,
targetInst,
nativeEvent,
nativeEventTarget
nativeEventTarget,
),
];
},
@@ -55,17 +55,16 @@ var activeElementValueProp = null;
function shouldUseChangeEvent(elem) {
var nodeName = elem.nodeName && elem.nodeName.toLowerCase();
return (
nodeName === 'select' ||
(nodeName === 'input' && elem.type === 'file')
nodeName === 'select' || (nodeName === 'input' && elem.type === 'file')
);
}
var doesChangeEventBubble = false;
if (ExecutionEnvironment.canUseDOM) {
// See `handleChange` comment below
doesChangeEventBubble = isEventSupported('change') && (
!document.documentMode || document.documentMode > 8
);
doesChangeEventBubble =
isEventSupported('change') &&
(!document.documentMode || document.documentMode > 8);
}
function manualDispatchChangeEvent(nativeEvent) {
@@ -73,7 +72,7 @@ function manualDispatchChangeEvent(nativeEvent) {
eventTypes.change,
activeElementInst,
nativeEvent,
getEventTarget(nativeEvent)
getEventTarget(nativeEvent),
);
EventPropagators.accumulateTwoPhaseDispatches(event);
@@ -111,19 +110,12 @@ function stopWatchingForChangeEventIE8() {
activeElementInst = null;
}
function getTargetInstForChangeEvent(
topLevelType,
targetInst
) {
function getTargetInstForChangeEvent(topLevelType, targetInst) {
if (topLevelType === 'topChange') {
return targetInst;
}
}
function handleEventsForChangeEventIE8(
topLevelType,
target,
targetInst
) {
function handleEventsForChangeEventIE8(topLevelType, target, targetInst) {
if (topLevelType === 'topFocus') {
// stopWatching() should be a noop here but we call it just in case we
// missed a blur event somehow.
@@ -134,7 +126,6 @@ function handleEventsForChangeEventIE8(
}
}
/**
* SECTION: handle `input` event
*/
@@ -144,9 +135,9 @@ if (ExecutionEnvironment.canUseDOM) {
// deleting text, so we ignore its input events.
// IE10+ fire input events to often, such when a placeholder
// changes or when an input with a placeholder is focused.
isInputEventSupported = isEventSupported('input') && (
!document.documentMode || document.documentMode > 11
);
isInputEventSupported =
isEventSupported('input') &&
(!document.documentMode || document.documentMode > 11);
}
/**
@@ -175,7 +166,7 @@ function startWatchingForValueChange(target, targetInst) {
activeElementValue = target.value;
activeElementValueProp = Object.getOwnPropertyDescriptor(
target.constructor.prototype,
'value'
'value',
);
// Not guarded in a canDefineProperty check: IE8 supports defineProperty only
@@ -184,7 +175,11 @@ function startWatchingForValueChange(target, targetInst) {
if (activeElement.attachEvent) {
activeElement.attachEvent('onpropertychange', handlePropertyChange);
} else {
activeElement.addEventListener('propertychange', handlePropertyChange, false);
activeElement.addEventListener(
'propertychange',
handlePropertyChange,
false,
);
}
}
@@ -203,7 +198,11 @@ function stopWatchingForValueChange() {
if (activeElement.detachEvent) {
activeElement.detachEvent('onpropertychange', handlePropertyChange);
} else {
activeElement.removeEventListener('propertychange', handlePropertyChange, false);
activeElement.removeEventListener(
'propertychange',
handlePropertyChange,
false,
);
}
activeElement = null;
@@ -232,10 +231,7 @@ function handlePropertyChange(nativeEvent) {
/**
* If a `change` event should be fired, returns the target's ID.
*/
function getTargetInstForInputEvent(
topLevelType,
targetInst
) {
function getTargetInstForInputEvent(topLevelType, targetInst) {
if (topLevelType === 'topInput') {
// In modern browsers (i.e., not IE8 or IE9), the input event is exactly
// what we want so fall through here and trigger an abstract event
@@ -243,11 +239,7 @@ function getTargetInstForInputEvent(
}
}
function handleEventsForInputEventIE(
topLevelType,
target,
targetInst
) {
function handleEventsForInputEventIE(topLevelType, target, targetInst) {
if (topLevelType === 'topFocus') {
// In IE8, we can capture almost all .value changes by adding a
// propertychange handler and looking for events with propertyName
@@ -270,13 +262,12 @@ function handleEventsForInputEventIE(
}
// For IE8 and IE9.
function getTargetInstForInputEventIE(
topLevelType,
targetInst
) {
if (topLevelType === 'topSelectionChange' ||
topLevelType === 'topKeyUp' ||
topLevelType === 'topKeyDown') {
function getTargetInstForInputEventIE(topLevelType, targetInst) {
if (
topLevelType === 'topSelectionChange' ||
topLevelType === 'topKeyUp' ||
topLevelType === 'topKeyDown'
) {
// On the selectionchange event, the target is just document which isn't
// helpful for us so just check activeElement instead.
//
@@ -294,7 +285,6 @@ function getTargetInstForInputEventIE(
}
}
/**
* SECTION: handle `click` event
*/
@@ -303,15 +293,13 @@ function shouldUseClickEvent(elem) {
// This approach works across all browsers, whereas `change` does not fire
// until `blur` in IE8.
return (
(elem.nodeName && elem.nodeName.toLowerCase() === 'input') &&
elem.nodeName &&
elem.nodeName.toLowerCase() === 'input' &&
(elem.type === 'checkbox' || elem.type === 'radio')
);
}
function getTargetInstForClickEvent(
topLevelType,
targetInst
) {
function getTargetInstForClickEvent(topLevelType, targetInst) {
if (topLevelType === 'topClick') {
return targetInst;
}
@@ -348,17 +336,17 @@ function handleControlledInputBlur(inst, node) {
* - select
*/
var ChangeEventPlugin = {
eventTypes: eventTypes,
extractEvents: function(
topLevelType,
targetInst,
nativeEvent,
nativeEventTarget
nativeEventTarget,
) {
var targetNode = targetInst ?
ReactDOMComponentTree.getNodeFromInstance(targetInst) : window;
var targetNode = targetInst
? ReactDOMComponentTree.getNodeFromInstance(targetInst)
: window;
var getTargetInstFunc, handleEventFunc;
if (shouldUseChangeEvent(targetNode)) {
@@ -385,7 +373,7 @@ var ChangeEventPlugin = {
eventTypes.change,
inst,
nativeEvent,
nativeEventTarget
nativeEventTarget,
);
event.type = 'change';
EventPropagators.accumulateTwoPhaseDispatches(event);
@@ -394,11 +382,7 @@ var ChangeEventPlugin = {
}
if (handleEventFunc) {
handleEventFunc(
topLevelType,
targetNode,
targetInst
);
handleEventFunc(topLevelType, targetNode, targetInst);
}
// When blurring, set the value attribute for number inputs
@@ -406,7 +390,6 @@ var ChangeEventPlugin = {
handleControlledInputBlur(targetInst, targetNode);
}
},
};
module.exports = ChangeEventPlugin;
@@ -18,22 +18,15 @@ var SyntheticMouseEvent = require('SyntheticMouseEvent');
var eventTypes = {
mouseEnter: {
registrationName: 'onMouseEnter',
dependencies: [
'topMouseOut',
'topMouseOver',
],
dependencies: ['topMouseOut', 'topMouseOver'],
},
mouseLeave: {
registrationName: 'onMouseLeave',
dependencies: [
'topMouseOut',
'topMouseOver',
],
dependencies: ['topMouseOut', 'topMouseOver'],
},
};
var EnterLeaveEventPlugin = {
eventTypes: eventTypes,
/**
@@ -47,14 +40,15 @@ var EnterLeaveEventPlugin = {
topLevelType,
targetInst,
nativeEvent,
nativeEventTarget
nativeEventTarget,
) {
if (topLevelType === 'topMouseOver' &&
(nativeEvent.relatedTarget || nativeEvent.fromElement)) {
if (
topLevelType === 'topMouseOver' &&
(nativeEvent.relatedTarget || nativeEvent.fromElement)
) {
return null;
}
if (topLevelType !== 'topMouseOut' &&
topLevelType !== 'topMouseOver') {
if (topLevelType !== 'topMouseOut' && topLevelType !== 'topMouseOver') {
// Must not be a mouse in or mouse out - ignoring.
return null;
}
@@ -78,8 +72,9 @@ var EnterLeaveEventPlugin = {
if (topLevelType === 'topMouseOut') {
from = targetInst;
var related = nativeEvent.relatedTarget || nativeEvent.toElement;
to = related ?
ReactDOMComponentTree.getClosestInstanceFromNode(related) : null;
to = related
? ReactDOMComponentTree.getClosestInstanceFromNode(related)
: null;
} else {
// Moving to a node from outside the window.
from = null;
@@ -91,16 +86,18 @@ var EnterLeaveEventPlugin = {
return null;
}
var fromNode =
from == null ? win : ReactDOMComponentTree.getNodeFromInstance(from);
var toNode =
to == null ? win : ReactDOMComponentTree.getNodeFromInstance(to);
var fromNode = from == null
? win
: ReactDOMComponentTree.getNodeFromInstance(from);
var toNode = to == null
? win
: ReactDOMComponentTree.getNodeFromInstance(to);
var leave = SyntheticMouseEvent.getPooled(
eventTypes.mouseLeave,
from,
nativeEvent,
nativeEventTarget
nativeEventTarget,
);
leave.type = 'mouseleave';
leave.target = fromNode;
@@ -110,7 +107,7 @@ var EnterLeaveEventPlugin = {
eventTypes.mouseEnter,
to,
nativeEvent,
nativeEventTarget
nativeEventTarget,
);
enter.type = 'mouseenter';
enter.target = toNode;
@@ -120,7 +117,6 @@ var EnterLeaveEventPlugin = {
return [leave, enter];
},
};
module.exports = EnterLeaveEventPlugin;
@@ -21,11 +21,10 @@ var getActiveElement = require('getActiveElement');
var isTextInputElement = require('isTextInputElement');
var shallowEqual = require('shallowEqual');
var skipSelectionChangeEvent = (
var skipSelectionChangeEvent =
ExecutionEnvironment.canUseDOM &&
'documentMode' in document &&
document.documentMode <= 11
);
document.documentMode <= 11;
var eventTypes = {
select: {
@@ -65,8 +64,10 @@ var hasListener = false;
* @return {object}
*/
function getSelection(node) {
if ('selectionStart' in node &&
ReactInputSelection.hasSelectionCapabilities(node)) {
if (
'selectionStart' in node &&
ReactInputSelection.hasSelectionCapabilities(node)
) {
return {
start: node.selectionStart,
end: node.selectionEnd,
@@ -101,9 +102,11 @@ function constructSelectEvent(nativeEvent, nativeEventTarget) {
// selection (this matches native `select` event behavior). In HTML5, select
// fires only on input and textarea thus if there's no focused element we
// won't dispatch.
if (mouseDown ||
activeElement == null ||
activeElement !== getActiveElement()) {
if (
mouseDown ||
activeElement == null ||
activeElement !== getActiveElement()
) {
return null;
}
@@ -116,7 +119,7 @@ function constructSelectEvent(nativeEvent, nativeEventTarget) {
eventTypes.select,
activeElementInst,
nativeEvent,
nativeEventTarget
nativeEventTarget,
);
syntheticEvent.type = 'select';
@@ -145,27 +148,29 @@ function constructSelectEvent(nativeEvent, nativeEventTarget) {
* - Fires after user input.
*/
var SelectEventPlugin = {
eventTypes: eventTypes,
extractEvents: function(
topLevelType,
targetInst,
nativeEvent,
nativeEventTarget
nativeEventTarget,
) {
if (!hasListener) {
return null;
}
var targetNode = targetInst ?
ReactDOMComponentTree.getNodeFromInstance(targetInst) : window;
var targetNode = targetInst
? ReactDOMComponentTree.getNodeFromInstance(targetInst)
: window;
switch (topLevelType) {
// Track the input node that has focus.
case 'topFocus':
if (isTextInputElement(targetNode) ||
targetNode.contentEditable === 'true') {
if (
isTextInputElement(targetNode) ||
targetNode.contentEditable === 'true'
) {
activeElement = targetNode;
activeElementInst = targetInst;
lastSelection = null;
@@ -176,7 +181,6 @@ var SelectEventPlugin = {
activeElementInst = null;
lastSelection = null;
break;
// Don't fire the event while the user is dragging. This matches the
// semantics of the native select event.
case 'topMouseDown':
@@ -186,7 +190,6 @@ var SelectEventPlugin = {
case 'topMouseUp':
mouseDown = false;
return constructSelectEvent(nativeEvent, nativeEventTarget);
// Chrome and IE fire non-standard event when selection is changed (and
// sometimes when it hasn't). IE's event fires out of order with respect
// to key and input events on deletion, so we discard it.
@@ -200,7 +203,7 @@ var SelectEventPlugin = {
if (skipSelectionChangeEvent) {
break;
}
// falls through
// falls through
case 'topKeyDown':
case 'topKeyUp':
return constructSelectEvent(nativeEvent, nativeEventTarget);
@@ -37,10 +37,7 @@ import type {
ReactSyntheticEvent,
} from 'ReactSyntheticEventType';
import type {ReactInstance} from 'ReactInstanceType';
import type {
EventTypes,
PluginModule,
} from 'PluginModuleType';
import type {EventTypes, PluginModule} from 'PluginModuleType';
/**
* Turns
@@ -151,13 +148,14 @@ function getDictionaryKey(inst: ReactInstance): string {
function isInteractive(tag) {
return (
tag === 'button' || tag === 'input' ||
tag === 'select' || tag === 'textarea'
tag === 'button' ||
tag === 'input' ||
tag === 'select' ||
tag === 'textarea'
);
}
var SimpleEventPlugin: PluginModule<MouseEvent> = {
eventTypes: eventTypes,
extractEvents: function(
@@ -211,7 +209,7 @@ var SimpleEventPlugin: PluginModule<MouseEvent> = {
if (getEventCharCode(nativeEvent) === 0) {
return null;
}
/* falls through */
/* falls through */
case 'topKeyDown':
case 'topKeyUp':
EventConstructor = SyntheticKeyboardEvent;
@@ -226,13 +224,13 @@ var SimpleEventPlugin: PluginModule<MouseEvent> = {
if (nativeEvent.button === 2) {
return null;
}
/* falls through */
/* falls through */
case 'topDoubleClick':
case 'topMouseDown':
case 'topMouseMove':
case 'topMouseUp':
// TODO: Disabled elements should not respond to mouse events
/* falls through */
// TODO: Disabled elements should not respond to mouse events
/* falls through */
case 'topMouseOut':
case 'topMouseOver':
case 'topContextMenu':
@@ -277,13 +275,13 @@ var SimpleEventPlugin: PluginModule<MouseEvent> = {
invariant(
EventConstructor,
'SimpleEventPlugin: Unhandled event type, `%s`.',
topLevelType
topLevelType,
);
var event = EventConstructor.getPooled(
dispatchConfig,
targetInst,
nativeEvent,
nativeEventTarget
nativeEventTarget,
);
EventPropagators.accumulateTwoPhaseDispatches(event);
return event;
@@ -306,7 +304,7 @@ var SimpleEventPlugin: PluginModule<MouseEvent> = {
onClickListeners[key] = EventListener.listen(
node,
'click',
emptyFunction
emptyFunction,
);
}
}
@@ -322,7 +320,6 @@ var SimpleEventPlugin: PluginModule<MouseEvent> = {
delete onClickListeners[key];
}
},
};
module.exports = SimpleEventPlugin;
@@ -21,10 +21,7 @@ var ViewportMetrics = require('ViewportMetrics');
var isStartish = EventPluginUtils.isStartish;
var isEndish = EventPluginUtils.isEndish;
import type {
EventTypes,
PluginModule,
} from 'PluginModuleType';
import type {EventTypes, PluginModule} from 'PluginModuleType';
import type {ReactInstance} from 'ReactInstanceType';
import type {TopLevelTypes} from 'EventConstants';
@@ -35,14 +32,10 @@ import type {TopLevelTypes} from 'EventConstants';
* "Indexable signature not found in Touch".
* See https://github.com/facebook/flow/issues/1323
*/
type TouchPropertyKey =
'clientX' |
'clientY' |
'pageX' |
'pageY';
type TouchPropertyKey = 'clientX' | 'clientY' | 'pageX' | 'pageY';
declare class _Touch extends Touch {
[key: TouchPropertyKey]: number;
[key: TouchPropertyKey]: number,
}
type AxisCoordinateData = {
@@ -81,20 +74,17 @@ function getAxisCoordOfEvent(
if (singleTouch) {
return singleTouch[axis.page];
}
return axis.page in nativeEvent ?
nativeEvent[axis.page] :
nativeEvent[axis.client] + ViewportMetrics[axis.envScroll];
return axis.page in nativeEvent
? nativeEvent[axis.page]
: nativeEvent[axis.client] + ViewportMetrics[axis.envScroll];
}
function getDistance(
coords: CoordinatesType,
nativeEvent: _Touch,
): number {
function getDistance(coords: CoordinatesType, nativeEvent: _Touch): number {
var pageX = getAxisCoordOfEvent(Axis.x, nativeEvent);
var pageY = getAxisCoordOfEvent(Axis.y, nativeEvent);
return Math.pow(
Math.pow(pageX - coords.x, 2) + Math.pow(pageY - coords.y, 2),
0.5
0.5,
);
}
@@ -105,11 +95,9 @@ var touchEvents = [
'topTouchMove',
];
var dependencies = [
'topMouseDown',
'topMouseMove',
'topMouseUp',
].concat(touchEvents);
var dependencies = ['topMouseDown', 'topMouseMove', 'topMouseUp'].concat(
touchEvents,
);
var eventTypes: EventTypes = {
touchTap: {
@@ -126,7 +114,6 @@ var usedTouchTime = 0;
var TOUCH_DELAY = 1000;
var TapEventPlugin: PluginModule<_Touch> = {
tapMoveThreshold: tapMoveThreshold,
eventTypes: eventTypes,
@@ -147,7 +134,7 @@ var TapEventPlugin: PluginModule<_Touch> = {
usedTouch = true;
usedTouchTime = Date.now();
} else {
if (usedTouch && (Date.now() - usedTouchTime < TOUCH_DELAY)) {
if (usedTouch && Date.now() - usedTouchTime < TOUCH_DELAY) {
return null;
}
}
@@ -158,7 +145,7 @@ var TapEventPlugin: PluginModule<_Touch> = {
eventTypes.touchTap,
targetInst,
nativeEvent,
nativeEventTarget
nativeEventTarget,
);
}
if (isStartish(topLevelType)) {
@@ -171,7 +158,6 @@ var TapEventPlugin: PluginModule<_Touch> = {
EventPropagators.accumulateTwoPhaseDispatches(event);
return event;
},
};
module.exports = TapEventPlugin;
@@ -15,12 +15,12 @@ var React = require('React');
var ReactTestUtils = require('ReactTestUtils');
var EventMapping = {
compositionstart : 'topCompositionStart',
compositionend : 'topCompositionEnd',
keyup : 'topKeyUp',
keydown : 'topKeyDown',
textInput : 'topTextInput',
textinput : null, // Not defined now
compositionstart: 'topCompositionStart',
compositionend: 'topCompositionEnd',
keyup: 'topKeyUp',
keydown: 'topKeyDown',
textInput: 'topTextInput',
textinput: null, // Not defined now
};
describe('BeforeInputEventPlugin', function() {
@@ -62,12 +62,12 @@ describe('BeforeInputEventPlugin', function() {
EventMapping[eventType],
ModuleCache.ReactDOMComponentTree.getInstanceFromNode(node),
evt,
node
node,
);
}
function setElementText(node) {
return (args) => node.innerHTML = args;
return args => (node.innerHTML = args);
}
function accumulateEvents(node, events) {
@@ -94,8 +94,10 @@ describe('BeforeInputEventPlugin', function() {
// Both are null. Expected.
} else if (actual === null) {
throw new EventMismatchError(idx, 'Expected not to be null');
} else if (expected.type === null
|| !(actual instanceof expected.type)) {
} else if (
expected.type === null ||
!(actual instanceof expected.type)
) {
throw new EventMismatchError(idx, 'Unexpected type: ' + actual);
} else {
// Type match.
@@ -103,8 +105,10 @@ describe('BeforeInputEventPlugin', function() {
if (!(expectedKey in actual)) {
throw new EventMismatchError(idx, 'KeyNotFound: ' + expectedKey);
} else if (actual[expectedKey] !== expected.data[expectedKey]) {
throw new EventMismatchError(idx,
'ValueMismatch: ' + actual[expectedKey]);
throw new EventMismatchError(
idx,
'ValueMismatch: ' + actual[expectedKey],
);
}
});
}
@@ -142,16 +146,26 @@ describe('BeforeInputEventPlugin', function() {
// textInput, SyntheticCompositionEvent at composition, and nothing from
// keyUp.
var Expected_Webkit = () => [
{type: ModuleCache.SyntheticCompositionEvent, data: {}}, {type: null},
{type: null}, {type: ModuleCache.SyntheticInputEvent, data: {data: 'A'}},
{type: null}, {type: null}, // textinput of A
{type: null}, {type: null}, // keyUp of 65
{type: null}, {type: ModuleCache.SyntheticInputEvent, data: {data: 'abc'}},
{type: null}, {type: null}, // textinput of abc
{type: null}, {type: null}, // keyUp of 32
{type: null}, {type: ModuleCache.SyntheticInputEvent, data: {data: 'xyz'}},
{type: null}, {type: null}, // textinput of xyz
{type: null}, {type: null}, // keyUp of 32
{type: ModuleCache.SyntheticCompositionEvent, data: {}},
{type: null},
{type: null},
{type: ModuleCache.SyntheticInputEvent, data: {data: 'A'}},
{type: null},
{type: null}, // textinput of A
{type: null},
{type: null}, // keyUp of 65
{type: null},
{type: ModuleCache.SyntheticInputEvent, data: {data: 'abc'}},
{type: null},
{type: null}, // textinput of abc
{type: null},
{type: null}, // keyUp of 32
{type: null},
{type: ModuleCache.SyntheticInputEvent, data: {data: 'xyz'}},
{type: null},
{type: null}, // textinput of xyz
{type: null},
{type: null}, // keyUp of 32
{type: ModuleCache.SyntheticCompositionEvent, data: {data: 'Hello'}},
{type: null},
];
@@ -161,19 +175,29 @@ describe('BeforeInputEventPlugin', function() {
// expected to be triggered at compositionend with a text of the target
// element, not event data.
var Expected_IE11 = () => [
{type: ModuleCache.SyntheticCompositionEvent, data: {}}, {type: null},
{type: null}, {type: null}, // textInput of A
{type: null}, {type: null}, // textinput of A
{type: null}, {type: null}, // keyUp of 65
{type: null}, {type: null}, // textInput of abc
{type: null}, {type: null}, // textinput of abc
{type: ModuleCache.SyntheticCompositionEvent, data: {}},
{type: null},
{type: null},
{type: null}, // textInput of A
{type: null},
{type: null}, // textinput of A
{type: null},
{type: null}, // keyUp of 65
{type: null},
{type: null}, // textInput of abc
{type: null},
{type: null}, // textinput of abc
// fallbackData should NOT be set at keyUp with any of END_KEYCODES
{type: null}, {type: null}, // keyUp of 32
{type: null},
{type: null}, // keyUp of 32
{type: null}, {type: null}, // textInput of xyz
{type: null}, {type: null}, // textinput of xyz
{type: null}, {type: null}, // keyUp of 32
{type: null},
{type: null}, // textInput of xyz
{type: null},
{type: null}, // textinput of xyz
{type: null},
{type: null}, // keyUp of 32
// fallbackData is retrieved from the element, which is XYZ,
// at a time of compositionend
@@ -194,18 +218,23 @@ describe('BeforeInputEventPlugin', function() {
var node = ModuleCache.ReactDOM.findDOMNode(rendered);
var events = [];
Scenario.forEach((el) =>
el.run.call(this, node, events).apply(this, el.arg));
Scenario.forEach(el => el.run.call(this, node, events).apply(this, el.arg));
verifyEvents(events, ExpectedResult());
}
it('extract onBeforeInput from native textinput events', function() {
TestEditableReactComponent(
simulateWebkit, Scenario_Composition, Expected_Webkit);
simulateWebkit,
Scenario_Composition,
Expected_Webkit,
);
});
it('extract onBeforeInput from fallback objects', function() {
TestEditableReactComponent(
simulateIE11, Scenario_Composition, Expected_IE11);
simulateIE11,
Scenario_Composition,
Expected_IE11,
);
});
});
@@ -23,7 +23,9 @@ describe('ChangeEventPlugin', () => {
expect(e.type).toBe('change');
}
var input = ReactTestUtils.renderIntoDocument(<input type="checkbox" onChange={cb}/>);
var input = ReactTestUtils.renderIntoDocument(
<input type="checkbox" onChange={cb} />,
);
ReactTestUtils.SimulateNative.click(input);
expect(called).toBe(1);
});
@@ -33,18 +33,21 @@ describe('EnterLeaveEventPlugin', () => {
var iframeDocument = iframe.contentDocument;
iframeDocument.write(
'<!DOCTYPE html><html><head></head><body><div></div></body></html>'
'<!DOCTYPE html><html><head></head><body><div></div></body></html>',
);
iframeDocument.close();
var component = ReactDOM.render(<div />, iframeDocument.body.getElementsByTagName('div')[0]);
var component = ReactDOM.render(
<div />,
iframeDocument.body.getElementsByTagName('div')[0],
);
var div = ReactDOM.findDOMNode(component);
var extracted = EnterLeaveEventPlugin.extractEvents(
'topMouseOver',
ReactDOMComponentTree.getInstanceFromNode(div),
{target: div},
div
div,
);
expect(extracted.length).toBe(2);
@@ -23,7 +23,7 @@ describe('SelectEventPlugin', () => {
topLevelEvent,
ReactDOMComponentTree.getInstanceFromNode(node),
{target: node},
node
node,
);
}
@@ -63,7 +63,7 @@ describe('SelectEventPlugin', () => {
var cb = jest.fn();
var rendered = ReactTestUtils.renderIntoDocument(
<WithSelect onSelect={cb} />
<WithSelect onSelect={cb} />,
);
var node = ReactDOM.findDOMNode(rendered);
@@ -11,7 +11,6 @@
'use strict';
describe('SimpleEventPlugin', function() {
var React;
var ReactDOM;
@@ -43,13 +42,13 @@ describe('SimpleEventPlugin', function() {
});
it('A non-interactive tags click when disabled', function() {
var element = (<div onClick={ onClick } />);
var element = <div onClick={onClick} />;
expectClickThru(mounted(element));
});
it('A non-interactive tags clicks bubble when disabled', function() {
var element = ReactTestUtils.renderIntoDocument(
<div onClick={onClick}><div /></div>
<div onClick={onClick}><div /></div>,
);
var child = ReactDOM.findDOMNode(element).firstChild;
@@ -59,7 +58,7 @@ describe('SimpleEventPlugin', function() {
it('does not register a click when clicking a child of a disabled element', function() {
var element = ReactTestUtils.renderIntoDocument(
<button onClick={onClick} disabled={true}><span /></button>
<button onClick={onClick} disabled={true}><span /></button>,
);
var child = ReactDOM.findDOMNode(element).querySelector('span');
@@ -69,7 +68,7 @@ describe('SimpleEventPlugin', function() {
it('triggers click events for children of disabled elements', function() {
var element = ReactTestUtils.renderIntoDocument(
<button disabled={true}><span onClick={onClick} /></button>
<button disabled={true}><span onClick={onClick} /></button>,
);
var child = ReactDOM.findDOMNode(element).querySelector('span');
@@ -81,7 +80,7 @@ describe('SimpleEventPlugin', function() {
var element = ReactTestUtils.renderIntoDocument(
<div onClickCapture={onClick}>
<button disabled={true}><span /></button>
</div>
</div>,
);
var child = ReactDOM.findDOMNode(element).querySelector('span');
@@ -91,7 +90,7 @@ describe('SimpleEventPlugin', function() {
it('triggers captured click events for children of disabled elements', function() {
var element = ReactTestUtils.renderIntoDocument(
<button disabled={true}><span onClickCapture={onClick} /></button>
<button disabled={true}><span onClickCapture={onClick} /></button>,
);
var child = ReactDOM.findDOMNode(element).querySelector('span');
@@ -100,9 +99,7 @@ describe('SimpleEventPlugin', function() {
});
['button', 'input', 'select', 'textarea'].forEach(function(tagName) {
describe(tagName, function() {
it('should forward clicks when it starts out not disabled', () => {
var element = React.createElement(tagName, {
onClick: onClick,
@@ -123,12 +120,12 @@ describe('SimpleEventPlugin', function() {
it('should forward clicks when it becomes not disabled', () => {
var container = document.createElement('div');
var element = ReactDOM.render(
React.createElement(tagName, { onClick: onClick, disabled: true }),
container
React.createElement(tagName, {onClick: onClick, disabled: true}),
container,
);
element = ReactDOM.render(
React.createElement(tagName, { onClick: onClick }),
container
React.createElement(tagName, {onClick: onClick}),
container,
);
expectClickThru(element);
});
@@ -136,12 +133,12 @@ describe('SimpleEventPlugin', function() {
it('should not forward clicks when it becomes disabled', () => {
var container = document.createElement('div');
var element = ReactDOM.render(
React.createElement(tagName, { onClick: onClick }),
container
React.createElement(tagName, {onClick: onClick}),
container,
);
element = ReactDOM.render(
React.createElement(tagName, { onClick: onClick, disabled: true }),
container
React.createElement(tagName, {onClick: onClick, disabled: true}),
container,
);
expectNoClickThru(element);
});
@@ -149,26 +146,25 @@ describe('SimpleEventPlugin', function() {
it('should work correctly if the listener is changed', () => {
var container = document.createElement('div');
var element = ReactDOM.render(
React.createElement(tagName, { onClick: onClick, disabled: true }),
container
React.createElement(tagName, {onClick: onClick, disabled: true}),
container,
);
element = ReactDOM.render(
React.createElement(tagName, { onClick: onClick, disabled: false }),
container
React.createElement(tagName, {onClick: onClick, disabled: false}),
container,
);
expectClickThru(element);
});
});
});
describe('iOS bubbling click fix', function() {
// See http://www.quirksmode.org/blog/archives/2010/09/click_event_del.html
it('does not add a local click to interactive elements', function() {
var container = document.createElement('div');
ReactDOM.render(<button onClick={ onClick } />, container);
ReactDOM.render(<button onClick={onClick} />, container);
var node = container.firstChild;
@@ -180,7 +176,7 @@ describe('SimpleEventPlugin', function() {
it('adds a local click listener to non-interactive elements', function() {
var container = document.createElement('div');
ReactDOM.render(<div onClick={ onClick } />, container);
ReactDOM.render(<div onClick={onClick} />, container);
var node = container.firstChild;
+7 -10
View File
@@ -34,11 +34,11 @@ function findDOMNode(componentOrElement) {
warning(
owner._warnedAboutRefsInRender,
'%s is accessing findDOMNode inside its render(). ' +
'render() should be a pure function of props and state. It should ' +
'never access something that requires stale data from the previous ' +
'render, such as refs. Move this logic to componentDidMount and ' +
'componentDidUpdate instead.',
owner.getName() || 'A component'
'render() should be a pure function of props and state. It should ' +
'never access something that requires stale data from the previous ' +
'render, such as refs. Move this logic to componentDidMount and ' +
'componentDidUpdate instead.',
owner.getName() || 'A component',
);
owner._warnedAboutRefsInRender = true;
}
@@ -57,15 +57,12 @@ function findDOMNode(componentOrElement) {
}
if (typeof componentOrElement.render === 'function') {
invariant(
false,
'findDOMNode was called on an unmounted component.'
);
invariant(false, 'findDOMNode was called on an unmounted component.');
} else {
invariant(
false,
'Element appears to be neither ReactComponent nor DOMNode (keys: %s)',
Object.keys(componentOrElement)
Object.keys(componentOrElement),
);
}
}
@@ -34,14 +34,17 @@ function SyntheticAnimationEvent(
dispatchConfig,
dispatchMarker,
nativeEvent,
nativeEventTarget
nativeEventTarget,
) {
return SyntheticEvent.call(this, dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget);
return SyntheticEvent.call(
this,
dispatchConfig,
dispatchMarker,
nativeEvent,
nativeEventTarget,
);
}
SyntheticEvent.augmentClass(
SyntheticAnimationEvent,
AnimationEventInterface
);
SyntheticEvent.augmentClass(SyntheticAnimationEvent, AnimationEventInterface);
module.exports = SyntheticAnimationEvent;
@@ -19,11 +19,9 @@ var SyntheticEvent = require('SyntheticEvent');
*/
var ClipboardEventInterface = {
clipboardData: function(event) {
return (
'clipboardData' in event ?
event.clipboardData :
window.clipboardData
);
return 'clipboardData' in event
? event.clipboardData
: window.clipboardData;
},
};
@@ -33,8 +31,19 @@ var ClipboardEventInterface = {
* @param {object} nativeEvent Native browser event.
* @extends {SyntheticUIEvent}
*/
function SyntheticClipboardEvent(dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget) {
return SyntheticEvent.call(this, dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget);
function SyntheticClipboardEvent(
dispatchConfig,
dispatchMarker,
nativeEvent,
nativeEventTarget,
) {
return SyntheticEvent.call(
this,
dispatchConfig,
dispatchMarker,
nativeEvent,
nativeEventTarget,
);
}
SyntheticEvent.augmentClass(SyntheticClipboardEvent, ClipboardEventInterface);
@@ -31,14 +31,20 @@ function SyntheticCompositionEvent(
dispatchConfig,
dispatchMarker,
nativeEvent,
nativeEventTarget
nativeEventTarget,
) {
return SyntheticEvent.call(this, dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget);
return SyntheticEvent.call(
this,
dispatchConfig,
dispatchMarker,
nativeEvent,
nativeEventTarget,
);
}
SyntheticEvent.augmentClass(
SyntheticCompositionEvent,
CompositionEventInterface
CompositionEventInterface,
);
module.exports = SyntheticCompositionEvent;
@@ -27,8 +27,19 @@ var DragEventInterface = {
* @param {object} nativeEvent Native browser event.
* @extends {SyntheticUIEvent}
*/
function SyntheticDragEvent(dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget) {
return SyntheticMouseEvent.call(this, dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget);
function SyntheticDragEvent(
dispatchConfig,
dispatchMarker,
nativeEvent,
nativeEventTarget,
) {
return SyntheticMouseEvent.call(
this,
dispatchConfig,
dispatchMarker,
nativeEvent,
nativeEventTarget,
);
}
SyntheticMouseEvent.augmentClass(SyntheticDragEvent, DragEventInterface);
@@ -27,8 +27,19 @@ var FocusEventInterface = {
* @param {object} nativeEvent Native browser event.
* @extends {SyntheticUIEvent}
*/
function SyntheticFocusEvent(dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget) {
return SyntheticUIEvent.call(this, dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget);
function SyntheticFocusEvent(
dispatchConfig,
dispatchMarker,
nativeEvent,
nativeEventTarget,
) {
return SyntheticUIEvent.call(
this,
dispatchConfig,
dispatchMarker,
nativeEvent,
nativeEventTarget,
);
}
SyntheticUIEvent.augmentClass(SyntheticFocusEvent, FocusEventInterface);
@@ -32,14 +32,17 @@ function SyntheticInputEvent(
dispatchConfig,
dispatchMarker,
nativeEvent,
nativeEventTarget
nativeEventTarget,
) {
return SyntheticEvent.call(this, dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget);
return SyntheticEvent.call(
this,
dispatchConfig,
dispatchMarker,
nativeEvent,
nativeEventTarget,
);
}
SyntheticEvent.augmentClass(
SyntheticInputEvent,
InputEventInterface
);
SyntheticEvent.augmentClass(SyntheticInputEvent, InputEventInterface);
module.exports = SyntheticInputEvent;
@@ -75,8 +75,19 @@ var KeyboardEventInterface = {
* @param {object} nativeEvent Native browser event.
* @extends {SyntheticUIEvent}
*/
function SyntheticKeyboardEvent(dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget) {
return SyntheticUIEvent.call(this, dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget);
function SyntheticKeyboardEvent(
dispatchConfig,
dispatchMarker,
nativeEvent,
nativeEventTarget,
) {
return SyntheticUIEvent.call(
this,
dispatchConfig,
dispatchMarker,
nativeEvent,
nativeEventTarget,
);
}
SyntheticUIEvent.augmentClass(SyntheticKeyboardEvent, KeyboardEventInterface);
@@ -46,22 +46,23 @@ var MouseEventInterface = {
},
buttons: null,
relatedTarget: function(event) {
return event.relatedTarget || (
event.fromElement === event.srcElement ?
event.toElement :
event.fromElement
return (
event.relatedTarget ||
(event.fromElement === event.srcElement
? event.toElement
: event.fromElement)
);
},
// "Proprietary" Interface.
pageX: function(event) {
return 'pageX' in event ?
event.pageX :
event.clientX + ViewportMetrics.currentScrollLeft;
return 'pageX' in event
? event.pageX
: event.clientX + ViewportMetrics.currentScrollLeft;
},
pageY: function(event) {
return 'pageY' in event ?
event.pageY :
event.clientY + ViewportMetrics.currentScrollTop;
return 'pageY' in event
? event.pageY
: event.clientY + ViewportMetrics.currentScrollTop;
},
};
@@ -71,8 +72,19 @@ var MouseEventInterface = {
* @param {object} nativeEvent Native browser event.
* @extends {SyntheticUIEvent}
*/
function SyntheticMouseEvent(dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget) {
return SyntheticUIEvent.call(this, dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget);
function SyntheticMouseEvent(
dispatchConfig,
dispatchMarker,
nativeEvent,
nativeEventTarget,
) {
return SyntheticUIEvent.call(
this,
dispatchConfig,
dispatchMarker,
nativeEvent,
nativeEventTarget,
);
}
SyntheticUIEvent.augmentClass(SyntheticMouseEvent, MouseEventInterface);
@@ -36,8 +36,19 @@ var TouchEventInterface = {
* @param {object} nativeEvent Native browser event.
* @extends {SyntheticUIEvent}
*/
function SyntheticTouchEvent(dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget) {
return SyntheticUIEvent.call(this, dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget);
function SyntheticTouchEvent(
dispatchConfig,
dispatchMarker,
nativeEvent,
nativeEventTarget,
) {
return SyntheticUIEvent.call(
this,
dispatchConfig,
dispatchMarker,
nativeEvent,
nativeEventTarget,
);
}
SyntheticUIEvent.augmentClass(SyntheticTouchEvent, TouchEventInterface);
@@ -34,14 +34,17 @@ function SyntheticTransitionEvent(
dispatchConfig,
dispatchMarker,
nativeEvent,
nativeEventTarget
nativeEventTarget,
) {
return SyntheticEvent.call(this, dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget);
return SyntheticEvent.call(
this,
dispatchConfig,
dispatchMarker,
nativeEvent,
nativeEventTarget,
);
}
SyntheticEvent.augmentClass(
SyntheticTransitionEvent,
TransitionEventInterface
);
SyntheticEvent.augmentClass(SyntheticTransitionEvent, TransitionEventInterface);
module.exports = SyntheticTransitionEvent;
@@ -50,8 +50,19 @@ var UIEventInterface = {
* @param {object} nativeEvent Native browser event.
* @extends {SyntheticEvent}
*/
function SyntheticUIEvent(dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget) {
return SyntheticEvent.call(this, dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget);
function SyntheticUIEvent(
dispatchConfig,
dispatchMarker,
nativeEvent,
nativeEventTarget,
) {
return SyntheticEvent.call(
this,
dispatchConfig,
dispatchMarker,
nativeEvent,
nativeEventTarget,
);
}
SyntheticEvent.augmentClass(SyntheticUIEvent, UIEventInterface);
@@ -19,20 +19,19 @@ var SyntheticMouseEvent = require('SyntheticMouseEvent');
*/
var WheelEventInterface = {
deltaX: function(event) {
return (
'deltaX' in event ? event.deltaX :
// Fallback to `wheelDeltaX` for Webkit and normalize (right is positive).
'wheelDeltaX' in event ? -event.wheelDeltaX : 0
);
return 'deltaX' in event
? event.deltaX
: // Fallback to `wheelDeltaX` for Webkit and normalize (right is positive).
'wheelDeltaX' in event ? -event.wheelDeltaX : 0;
},
deltaY: function(event) {
return (
'deltaY' in event ? event.deltaY :
// Fallback to `wheelDeltaY` for Webkit and normalize (down is positive).
'wheelDeltaY' in event ? -event.wheelDeltaY :
// Fallback to `wheelDelta` for IE<9 and normalize (down is positive).
'wheelDelta' in event ? -event.wheelDelta : 0
);
return 'deltaY' in event
? event.deltaY
: // Fallback to `wheelDeltaY` for Webkit and normalize (down is positive).
'wheelDeltaY' in event
? -event.wheelDeltaY
: // Fallback to `wheelDelta` for IE<9 and normalize (down is positive).
'wheelDelta' in event ? -event.wheelDelta : 0;
},
deltaZ: null,
@@ -49,8 +48,19 @@ var WheelEventInterface = {
* @param {object} nativeEvent Native browser event.
* @extends {SyntheticMouseEvent}
*/
function SyntheticWheelEvent(dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget) {
return SyntheticMouseEvent.call(this, dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget);
function SyntheticWheelEvent(
dispatchConfig,
dispatchMarker,
nativeEvent,
nativeEventTarget,
) {
return SyntheticMouseEvent.call(
this,
dispatchConfig,
dispatchMarker,
nativeEvent,
nativeEventTarget,
);
}
SyntheticMouseEvent.augmentClass(SyntheticWheelEvent, WheelEventInterface);
@@ -29,12 +29,15 @@ describe('SyntheticClipboardEvent', () => {
describe('when event has clipboardData', () => {
it("returns event's clipboardData", () => {
// Mock clipboardData since native implementation doesn't have a constructor
var clipboardData = jasmine.createSpyObj(
'clipboardData',
['dropEffect', 'effectAllowed', 'files', 'items', 'types']
);
var clipboardData = jasmine.createSpyObj('clipboardData', [
'dropEffect',
'effectAllowed',
'files',
'items',
'types',
]);
var clipboardEvent = createEvent({clipboardData: clipboardData});
expect(clipboardEvent.clipboardData).toBe(clipboardData);
});
});
@@ -53,9 +53,9 @@ describe('SyntheticEvent', () => {
});
it('should be prevented if nativeEvent is prevented', () => {
expect(
createEvent({defaultPrevented: true}).isDefaultPrevented()
).toBe(true);
expect(createEvent({defaultPrevented: true}).isDefaultPrevented()).toBe(
true,
);
expect(createEvent({returnValue: false}).isDefaultPrevented()).toBe(true);
});
@@ -91,10 +91,10 @@ describe('SyntheticEvent', () => {
// assert the first warning for accessing `type`
expect(console.error.calls.argsFor(0)[0]).toBe(
'Warning: This synthetic event is reused for performance reasons. If ' +
'you\'re seeing this, you\'re accessing the property `type` on a ' +
'released/nullified synthetic event. This is set to null. If you must ' +
'keep the original synthetic event around, use event.persist(). ' +
'See https://fb.me/react-event-pooling for more information.'
"you're seeing this, you're accessing the property `type` on a " +
'released/nullified synthetic event. This is set to null. If you must ' +
'keep the original synthetic event around, use event.persist(). ' +
'See https://fb.me/react-event-pooling for more information.',
);
});
@@ -103,14 +103,14 @@ describe('SyntheticEvent', () => {
var target = document.createElement('div');
var syntheticEvent = createEvent({srcElement: target});
syntheticEvent.destructor();
expect(syntheticEvent.type = 'MouseEvent').toBe('MouseEvent');
expect((syntheticEvent.type = 'MouseEvent')).toBe('MouseEvent');
expect(console.error.calls.count()).toBe(1);
expect(console.error.calls.argsFor(0)[0]).toBe(
'Warning: This synthetic event is reused for performance reasons. If ' +
'you\'re seeing this, you\'re setting the property `type` on a ' +
'released/nullified synthetic event. This is effectively a no-op. If you must ' +
'keep the original synthetic event around, use event.persist(). ' +
'See https://fb.me/react-event-pooling for more information.'
"you're seeing this, you're setting the property `type` on a " +
'released/nullified synthetic event. This is effectively a no-op. If you must ' +
'keep the original synthetic event around, use event.persist(). ' +
'See https://fb.me/react-event-pooling for more information.',
);
});
@@ -122,10 +122,10 @@ describe('SyntheticEvent', () => {
expect(console.error.calls.count()).toBe(1);
expect(console.error.calls.argsFor(0)[0]).toBe(
'Warning: This synthetic event is reused for performance reasons. If ' +
'you\'re seeing this, you\'re accessing the method `preventDefault` on a ' +
'released/nullified synthetic event. This is a no-op function. If you must ' +
'keep the original synthetic event around, use event.persist(). ' +
'See https://fb.me/react-event-pooling for more information.'
"you're seeing this, you're accessing the method `preventDefault` on a " +
'released/nullified synthetic event. This is a no-op function. If you must ' +
'keep the original synthetic event around, use event.persist(). ' +
'See https://fb.me/react-event-pooling for more information.',
);
});
@@ -137,39 +137,42 @@ describe('SyntheticEvent', () => {
expect(console.error.calls.count()).toBe(1);
expect(console.error.calls.argsFor(0)[0]).toBe(
'Warning: This synthetic event is reused for performance reasons. If ' +
'you\'re seeing this, you\'re accessing the method `stopPropagation` on a ' +
'released/nullified synthetic event. This is a no-op function. If you must ' +
'keep the original synthetic event around, use event.persist(). ' +
'See https://fb.me/react-event-pooling for more information.'
"you're seeing this, you're accessing the method `stopPropagation` on a " +
'released/nullified synthetic event. This is a no-op function. If you must ' +
'keep the original synthetic event around, use event.persist(). ' +
'See https://fb.me/react-event-pooling for more information.',
);
});
// TODO: reenable this test. We are currently silencing these warnings when
// using TestUtils.Simulate to avoid spurious warnings that result from the
// way we simulate events.
xit('should properly log warnings when events simulated with rendered components', () => {
spyOn(console, 'error');
var event;
var element = document.createElement('div');
function assignEvent(e) {
event = e;
}
var instance = ReactDOM.render(<div onClick={assignEvent} />, element);
ReactTestUtils.Simulate.click(ReactDOM.findDOMNode(instance));
expect(console.error.calls.count()).toBe(0);
xit(
'should properly log warnings when events simulated with rendered components',
() => {
spyOn(console, 'error');
var event;
var element = document.createElement('div');
function assignEvent(e) {
event = e;
}
var instance = ReactDOM.render(<div onClick={assignEvent} />, element);
ReactTestUtils.Simulate.click(ReactDOM.findDOMNode(instance));
expect(console.error.calls.count()).toBe(0);
// access a property to cause the warning
event.nativeEvent; // eslint-disable-line no-unused-expressions
// access a property to cause the warning
event.nativeEvent; // eslint-disable-line no-unused-expressions
expect(console.error.calls.count()).toBe(1);
expect(console.error.calls.argsFor(0)[0]).toBe(
'Warning: This synthetic event is reused for performance reasons. If ' +
'you\'re seeing this, you\'re accessing the property `nativeEvent` on a ' +
'released/nullified synthetic event. This is set to null. If you must ' +
'keep the original synthetic event around, use event.persist(). ' +
'See https://fb.me/react-event-pooling for more information.'
);
});
expect(console.error.calls.count()).toBe(1);
expect(console.error.calls.argsFor(0)[0]).toBe(
'Warning: This synthetic event is reused for performance reasons. If ' +
"you're seeing this, you're accessing the property `nativeEvent` on a " +
'released/nullified synthetic event. This is set to null. If you must ' +
'keep the original synthetic event around, use event.persist(). ' +
'See https://fb.me/react-event-pooling for more information.',
);
},
);
it('should warn if Proxy is supported and the synthetic event is added a property', () => {
spyOn(console, 'error');
@@ -181,9 +184,9 @@ describe('SyntheticEvent', () => {
expect(console.error.calls.count()).toBe(1);
expect(console.error.calls.argsFor(0)[0]).toBe(
'Warning: This synthetic event is reused for performance reasons. If ' +
'you\'re seeing this, you\'re adding a new property in the synthetic ' +
'event object. The property is never released. ' +
'See https://fb.me/react-event-pooling for more information.'
"you're seeing this, you're adding a new property in the synthetic " +
'event object. The property is never released. ' +
'See https://fb.me/react-event-pooling for more information.',
);
} else {
expect(console.error.calls.count()).toBe(0);
@@ -67,5 +67,4 @@ describe('SyntheticWheelEvent', () => {
syntheticEvent.persist();
expect(syntheticEvent.isPersistent()).toBe(true);
});
});
@@ -37,14 +37,16 @@ function getNodeAfter(parentNode, node) {
* @param {number} index Index at which to insert the child.
* @internal
*/
var insertChildAt = createMicrosoftUnsafeLocalFunction(
function(parentNode, childNode, referenceNode) {
// We rely exclusively on `insertBefore(node, null)` instead of also using
// `appendChild(node)`. (Using `undefined` is not allowed by all browsers so
// we are careful to use `null`.)
parentNode.insertBefore(childNode, referenceNode);
}
);
var insertChildAt = createMicrosoftUnsafeLocalFunction(function(
parentNode,
childNode,
referenceNode,
) {
// We rely exclusively on `insertBefore(node, null)` instead of also using
// `appendChild(node)`. (Using `undefined` is not allowed by all browsers so
// we are careful to use `null`.)
parentNode.insertBefore(childNode, referenceNode);
});
function insertLazyTreeChildAt(parentNode, childTree, referenceNode) {
DOMLazyTree.insertTreeBefore(parentNode, childTree, referenceNode);
@@ -72,7 +74,7 @@ function moveDelimitedText(
parentNode,
openingComment,
closingComment,
referenceNode
referenceNode,
) {
var node = openingComment;
while (true) {
@@ -107,7 +109,7 @@ function replaceDelimitedText(openingComment, closingComment, stringText) {
insertChildAt(
parentNode,
document.createTextNode(stringText),
nodeAfterComment
nodeAfterComment,
);
}
} else {
@@ -123,7 +125,8 @@ function replaceDelimitedText(openingComment, closingComment, stringText) {
if (__DEV__) {
ReactInstrumentation.debugTool.onHostOperation({
instanceID: ReactDOMComponentTree.getInstanceFromNode(openingComment)._debugID,
instanceID: ReactDOMComponentTree.getInstanceFromNode(openingComment)
._debugID,
type: 'replace text',
payload: stringText,
});
@@ -157,7 +160,6 @@ if (__DEV__) {
* Operations for updating with DOM children.
*/
var DOMChildrenOperations = {
dangerouslyReplaceNodeWithMarkup: dangerouslyReplaceNodeWithMarkup,
replaceDelimitedText: replaceDelimitedText,
@@ -171,8 +173,9 @@ var DOMChildrenOperations = {
*/
processUpdates: function(parentNode, updates) {
if (__DEV__) {
var parentNodeDebugID =
ReactDOMComponentTree.getInstanceFromNode(parentNode)._debugID;
var parentNodeDebugID = ReactDOMComponentTree.getInstanceFromNode(
parentNode,
)._debugID;
}
for (var k = 0; k < updates.length; k++) {
@@ -182,13 +185,16 @@ var DOMChildrenOperations = {
insertLazyTreeChildAt(
parentNode,
update.content,
getNodeAfter(parentNode, update.afterNode)
getNodeAfter(parentNode, update.afterNode),
);
if (__DEV__) {
ReactInstrumentation.debugTool.onHostOperation({
instanceID: parentNodeDebugID,
type: 'insert child',
payload: {toIndex: update.toIndex, content: update.content.toString()},
payload: {
toIndex: update.toIndex,
content: update.content.toString(),
},
});
}
break;
@@ -196,7 +202,7 @@ var DOMChildrenOperations = {
moveChild(
parentNode,
update.fromNode,
getNodeAfter(parentNode, update.afterNode)
getNodeAfter(parentNode, update.afterNode),
);
if (__DEV__) {
ReactInstrumentation.debugTool.onHostOperation({
@@ -207,10 +213,7 @@ var DOMChildrenOperations = {
}
break;
case 'SET_MARKUP':
setInnerHTML(
parentNode,
update.content
);
setInnerHTML(parentNode, update.content);
if (__DEV__) {
ReactInstrumentation.debugTool.onHostOperation({
instanceID: parentNodeDebugID,
@@ -220,10 +223,7 @@ var DOMChildrenOperations = {
}
break;
case 'TEXT_CONTENT':
setTextContent(
parentNode,
update.content
);
setTextContent(parentNode, update.content);
if (__DEV__) {
ReactInstrumentation.debugTool.onHostOperation({
instanceID: parentNodeDebugID,
@@ -245,7 +245,6 @@ var DOMChildrenOperations = {
}
}
},
};
module.exports = DOMChildrenOperations;
+30 -29
View File
@@ -31,14 +31,12 @@ var DOCUMENT_FRAGMENT_NODE_TYPE = 11;
*
* See https://github.com/spicyj/innerhtml-vs-createelement-vs-clonenode.
*/
var enableLazy = (
typeof document !== 'undefined' &&
typeof document.documentMode === 'number'
||
typeof navigator !== 'undefined' &&
typeof navigator.userAgent === 'string' &&
/\bEdge\/\d/.test(navigator.userAgent)
);
var enableLazy =
(typeof document !== 'undefined' &&
typeof document.documentMode === 'number') ||
(typeof navigator !== 'undefined' &&
typeof navigator.userAgent === 'string' &&
/\bEdge\/\d/.test(navigator.userAgent));
function insertTreeChildren(tree) {
if (!enableLazy) {
@@ -57,28 +55,31 @@ function insertTreeChildren(tree) {
}
}
var insertTreeBefore = createMicrosoftUnsafeLocalFunction(
function(parentNode, tree, referenceNode) {
// DocumentFragments aren't actually part of the DOM after insertion so
// appending children won't update the DOM. We need to ensure the fragment
// is properly populated first, breaking out of our lazy approach for just
// this level. Also, some <object> plugins (like Flash Player) will read
// <param> nodes immediately upon insertion into the DOM, so <object>
// must also be populated prior to insertion into the DOM.
if (tree.node.nodeType === DOCUMENT_FRAGMENT_NODE_TYPE
||
tree.node.nodeType === ELEMENT_NODE_TYPE &&
tree.node.nodeName.toLowerCase() === 'object' &&
(tree.node.namespaceURI == null ||
tree.node.namespaceURI === DOMNamespaces.html)) {
insertTreeChildren(tree);
parentNode.insertBefore(tree.node, referenceNode);
} else {
parentNode.insertBefore(tree.node, referenceNode);
insertTreeChildren(tree);
}
var insertTreeBefore = createMicrosoftUnsafeLocalFunction(function(
parentNode,
tree,
referenceNode,
) {
// DocumentFragments aren't actually part of the DOM after insertion so
// appending children won't update the DOM. We need to ensure the fragment
// is properly populated first, breaking out of our lazy approach for just
// this level. Also, some <object> plugins (like Flash Player) will read
// <param> nodes immediately upon insertion into the DOM, so <object>
// must also be populated prior to insertion into the DOM.
if (
tree.node.nodeType === DOCUMENT_FRAGMENT_NODE_TYPE ||
(tree.node.nodeType === ELEMENT_NODE_TYPE &&
tree.node.nodeName.toLowerCase() === 'object' &&
(tree.node.namespaceURI == null ||
tree.node.namespaceURI === DOMNamespaces.html))
) {
insertTreeChildren(tree);
parentNode.insertBefore(tree.node, referenceNode);
} else {
parentNode.insertBefore(tree.node, referenceNode);
insertTreeChildren(tree);
}
);
});
function replaceChildWithTree(oldNode, newTree) {
oldNode.parentNode.replaceChild(newTree.node, oldNode);
@@ -12,7 +12,6 @@
'use strict';
var ViewportMetrics = {
currentScrollLeft: 0,
currentScrollTop: 0,
@@ -21,7 +20,6 @@ var ViewportMetrics = {
ViewportMetrics.currentScrollLeft = scrollPosition.x;
ViewportMetrics.currentScrollTop = scrollPosition.y;
},
};
module.exports = ViewportMetrics;
@@ -17,9 +17,10 @@ describe('getEventCharCode', () => {
describe('when charCode is present in nativeEvent', () => {
describe('when charCode is 0 and keyCode is 13', () => {
it('returns 13', () => {
var nativeEvent = new KeyboardEvent(
'keypress', {charCode: 0, keyCode: 13}
);
var nativeEvent = new KeyboardEvent('keypress', {
charCode: 0,
keyCode: 13,
});
expect(getEventCharCode(nativeEvent)).toBe(13);
});
@@ -62,7 +63,7 @@ describe('getEventCharCode', () => {
describe('when charCode is not present in nativeEvent', () => {
describe('when keyCode is 32 or bigger', () => {
it('returns keyCode', () => {
var nativeEvent = {'keyCode': 32};
var nativeEvent = {keyCode: 32};
expect(getEventCharCode(nativeEvent)).toBe(32);
});
@@ -71,7 +72,7 @@ describe('getEventCharCode', () => {
describe('when keyCode is smaller than 32', () => {
describe('when keyCode is 13', () => {
it('returns 13', () => {
var nativeEvent = {'keyCode': 13};
var nativeEvent = {keyCode: 13};
expect(getEventCharCode(nativeEvent)).toBe(13);
});
@@ -79,7 +80,7 @@ describe('getEventCharCode', () => {
describe('when keyCode is not 13', () => {
it('returns 0', () => {
var nativeEvent = {'keyCode': 31};
var nativeEvent = {keyCode: 31};
expect(getEventCharCode(nativeEvent)).toBe(0);
});

Some files were not shown because too many files have changed in this diff Show More