mirror of
https://github.com/facebook/react.git
synced 2025-11-01 09:12:30 +00:00
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:
@@ -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",
|
||||
|
||||
@@ -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,
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -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');
|
||||
|
||||
@@ -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');
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
@@ -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',
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -30,7 +30,7 @@ var LinkedStateMixin = {
|
||||
linkState: function(key) {
|
||||
return new ReactLink(
|
||||
this.state[key],
|
||||
ReactStateSetters.createStateKeySetter(this, key)
|
||||
ReactStateSetters.createStateKeySetter(this, key),
|
||||
);
|
||||
},
|
||||
};
|
||||
|
||||
@@ -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,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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',
|
||||
);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
@@ -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" />]);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
@@ -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);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
@@ -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'),
|
||||
|
||||
|
||||
@@ -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);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -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
@@ -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
|
||||
|
||||
@@ -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);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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: server text</div>);
|
||||
<div>This markup contains an nbsp entity: server text</div>,
|
||||
);
|
||||
div.innerHTML = markup;
|
||||
|
||||
spyOn(console, 'error');
|
||||
ReactDOM.render(
|
||||
<div>This markup contains an nbsp entity: client text</div>,
|
||||
div
|
||||
div,
|
||||
);
|
||||
expect(console.error.calls.count()).toBe(1);
|
||||
expect(console.error.calls.argsFor(0)[0]).toContain(
|
||||
' (client) nbsp entity: client text</div>\n' +
|
||||
' (server) nbsp entity: server text</div>'
|
||||
' (server) nbsp entity: 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;
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
Reference in New Issue
Block a user