Fix __proto__ bug in ReactDOMSelect (#9536)

https://twitter.com/rauschma/status/857307345231249409
This commit is contained in:
Ben Alpert
2017-04-29 08:23:00 -07:00
committed by GitHub
parent 50d6f9656d
commit f677bfc964
4 changed files with 61 additions and 4 deletions
+2
View File
@@ -1529,8 +1529,10 @@ src/renderers/dom/shared/wrappers/__tests__/ReactDOMSelect-test.js
* should not control when using `defaultValue`
* should allow setting `defaultValue` with multiple
* should allow setting `value`
* should allow setting `value` to __proto__
* should not throw with `value` and without children
* should allow setting `value` with multiple
* should allow setting `value` to __proto__ with multiple
* should not select other options automatically
* should reset child options selected when they are changed and `value` is set
* should allow setting `value` with `objectToString`
@@ -89,10 +89,11 @@ function updateOptions(
let selectedValues = (propValue: Array<string>);
let selectedValue = {};
for (let i = 0; i < selectedValues.length; i++) {
selectedValue['' + selectedValues[i]] = true;
// Prefix to avoid chaos with special keys.
selectedValue['$' + selectedValues[i]] = true;
}
for (let i = 0; i < options.length; i++) {
var selected = selectedValue.hasOwnProperty(options[i].value);
var selected = selectedValue.hasOwnProperty('$' + options[i].value);
if (options[i].selected !== selected) {
options[i].selected = selected;
}
@@ -128,6 +128,29 @@ describe('ReactDOMSelect', () => {
expect(node.value).toEqual('gorilla');
});
it('should allow setting `value` to __proto__', () => {
var stub = (
<select value="__proto__" onChange={noop}>
<option value="monkey">A monkey!</option>
<option value="__proto__">A giraffe!</option>
<option value="gorilla">A gorilla!</option>
</select>
);
var options = stub.props.children;
var container = document.createElement('div');
stub = ReactDOM.render(stub, container);
var node = ReactDOM.findDOMNode(stub);
expect(node.value).toBe('__proto__');
// Changing the `value` prop should change the selected option.
ReactDOM.render(
<select value="gorilla" onChange={noop}>{options}</select>,
container,
);
expect(node.value).toEqual('gorilla');
});
it('should not throw with `value` and without children', () => {
var stub = <select value="dummy" onChange={noop} />;
@@ -166,6 +189,36 @@ describe('ReactDOMSelect', () => {
expect(node.options[2].selected).toBe(false); // gorilla
});
it('should allow setting `value` to __proto__ with multiple', () => {
var stub = (
<select multiple={true} value={['__proto__', 'gorilla']} onChange={noop}>
<option value="monkey">A monkey!</option>
<option value="__proto__">A __proto__!</option>
<option value="gorilla">A gorilla!</option>
</select>
);
var options = stub.props.children;
var container = document.createElement('div');
stub = ReactDOM.render(stub, container);
var node = ReactDOM.findDOMNode(stub);
expect(node.options[0].selected).toBe(false); // monkey
expect(node.options[1].selected).toBe(true); // __proto__
expect(node.options[2].selected).toBe(true); // gorilla
// Changing the `value` prop should change the selected options.
ReactDOM.render(
<select multiple={true} value={['monkey']} onChange={noop}>
{options}
</select>,
container,
);
expect(node.options[0].selected).toBe(true); // monkey
expect(node.options[1].selected).toBe(false); // __proto__
expect(node.options[2].selected).toBe(false); // gorilla
});
it('should not select other options automatically', () => {
var stub = (
<select multiple={true} value={['12']} onChange={noop}>
@@ -84,10 +84,11 @@ function updateOptions(inst, multiple, propValue) {
if (multiple) {
let selectedValue = {};
for (let i = 0; i < propValue.length; i++) {
selectedValue['' + propValue[i]] = true;
// Prefix to avoid chaos with special keys.
selectedValue['$' + propValue[i]] = true;
}
for (let i = 0; i < options.length; i++) {
var selected = selectedValue.hasOwnProperty(options[i].value);
var selected = selectedValue.hasOwnProperty('$' + options[i].value);
if (options[i].selected !== selected) {
options[i].selected = selected;
}