From 07c0bc6166013fc56edd8310bd97267549e5c708 Mon Sep 17 00:00:00 2001 From: Ben Alpert Date: Wed, 23 Dec 2015 15:34:48 -0800 Subject: [PATCH] Set input .type before .value always In IE11 (and below), if you run ``` var input = document.createElement('input'); input.value = 'wat'; input.type = 'radio'; console.log(input.value); ``` you get the string "on" logged. Because that makes sense. So we set the type first. --- .../dom/client/wrappers/ReactDOMInput.js | 6 +++- .../wrappers/__tests__/ReactDOMInput-test.js | 28 +++++++++++++++++++ 2 files changed, 33 insertions(+), 1 deletion(-) diff --git a/src/renderers/dom/client/wrappers/ReactDOMInput.js b/src/renderers/dom/client/wrappers/ReactDOMInput.js index 682a34961a..039cadc5e0 100644 --- a/src/renderers/dom/client/wrappers/ReactDOMInput.js +++ b/src/renderers/dom/client/wrappers/ReactDOMInput.js @@ -67,7 +67,11 @@ var ReactDOMInput = { var value = LinkedValueUtils.getValue(props); var checked = LinkedValueUtils.getChecked(props); - var nativeProps = assign({}, props, { + var nativeProps = assign({ + // Make sure we set .type before any other properties (setting .value + // before .type means .value is lost in IE11 and below) + type: undefined, + }, props, { defaultChecked: undefined, defaultValue: undefined, value: value != null ? value : inst._wrapperState.initialValue, diff --git a/src/renderers/dom/client/wrappers/__tests__/ReactDOMInput-test.js b/src/renderers/dom/client/wrappers/__tests__/ReactDOMInput-test.js index ffa90a059d..09d4772e91 100644 --- a/src/renderers/dom/client/wrappers/__tests__/ReactDOMInput-test.js +++ b/src/renderers/dom/client/wrappers/__tests__/ReactDOMInput-test.js @@ -414,4 +414,32 @@ describe('ReactDOMInput', function() { ReactTestUtils.renderIntoDocument(); expect(console.error.argsForCall.length).toBe(1); }); + + it('sets type before value always', function() { + var log = []; + var originalCreateElement = document.createElement; + spyOn(document, 'createElement').andCallFake(function(type) { + var el = originalCreateElement.apply(this, arguments); + if (type === 'input') { + Object.defineProperty(el, 'value', { + get: function() {}, + set: function() { + log.push('set value'); + }, + }); + spyOn(el, 'setAttribute').andCallFake(function(name, value) { + log.push('set ' + name); + }); + } + return el; + }); + + ReactTestUtils.renderIntoDocument(); + // Setting value before type does bad things. Make sure we set type first. + expect(log).toEqual([ + 'set data-reactroot', + 'set type', + 'set value', + ]); + }); });