@samitouri / QOS-React-2 / commits / 30ef056731

Moved unknown-prop warning into a devtool

Jim committed Dec 3, 2015 at 07:02 UTC 30ef056731f10a094661b0d288c68fbe0c044161
5 files changed +118 -95
src/renderers/dom/ReactDOM.js
+3
@@ -15,6 +15,7 @@
15
16 var ReactDOMComponentTree = require('ReactDOMComponentTree');
17 var ReactDOMDevtools = require('ReactDOMDevtools');
18 +var ReactDOMUnknownPropertyDevtool = require('ReactDOMUnknownPropertyDevtool');
19 var ReactDefaultInjection = require('ReactDefaultInjection');
20 var ReactMount = require('ReactMount');
21 var ReactPerf = require('ReactPerf');
@@ -136,6 +137,8 @@ if (__DEV__) {
137 break;
138 }
139 }
140 +
141 + ReactDOMDevtools.addDevtool(new ReactDOMUnknownPropertyDevtool());
142 }
143 }
144
src/renderers/dom/shared/DOMPropertyOperations.js
+4 -60
@@ -12,7 +12,7 @@
12 'use strict';
13
14 var DOMProperty = require('DOMProperty');
15 -var EventPluginRegistry = require('EventPluginRegistry');
15 +var ReactDOMDevtools = require('ReactDOMDevtools');
16 var ReactPerf = require('ReactPerf');
17
18 var quoteAttributeValueForBrowser = require('quoteAttributeValueForBrowser');
@@ -51,59 +51,6 @@ function shouldIgnoreValue(propertyInfo, value) {
51 (propertyInfo.hasOverloadedBooleanValue && value === false);
52 }
53
54 -if (__DEV__) {
55 - var reactProps = {
56 - children: true,
57 - dangerouslySetInnerHTML: true,
58 - key: true,
59 - ref: true,
60 - };
61 - var warnedProperties = {};
62 -
63 - var warnUnknownProperty = function(name) {
64 - if (reactProps.hasOwnProperty(name) && reactProps[name] ||
65 - warnedProperties.hasOwnProperty(name) && warnedProperties[name]) {
66 - return;
67 - }
68 -
69 - warnedProperties[name] = true;
70 - var lowerCasedName = name.toLowerCase();
71 -
72 - // data-* attributes should be lowercase; suggest the lowercase version
73 - var standardName = (
74 - DOMProperty.isCustomAttribute(lowerCasedName) ?
75 - lowerCasedName :
76 - DOMProperty.getPossibleStandardName.hasOwnProperty(lowerCasedName) ?
77 - DOMProperty.getPossibleStandardName[lowerCasedName] :
78 - null
79 - );
80 -
81 - // For now, only warn when we have a suggested correction. This prevents
82 - // logging too much when using transferPropsTo.
83 - warning(
84 - standardName == null,
85 - 'Unknown DOM property %s. Did you mean %s?',
86 - name,
87 - standardName
88 - );
89 -
90 - var registrationName = (
91 - EventPluginRegistry.possibleRegistrationNames.hasOwnProperty(
92 - lowerCasedName
93 - ) ?
94 - EventPluginRegistry.possibleRegistrationNames[lowerCasedName] :
95 - null
96 - );
97 -
98 - warning(
99 - registrationName == null,
100 - 'Unknown event handler property %s. Did you mean `%s`?',
101 - name,
102 - registrationName
103 - );
104 - };
105 -}
106 -
54 /**
55 * Operations for dealing with DOM properties.
56 */
@@ -140,6 +87,7 @@ var DOMPropertyOperations = {
87 * @return {?string} Markup string, or null if the property was invalid.
88 */
89 createMarkupForProperty: function(name, value) {
90 + ReactDOMDevtools.emitEvent('createMarkupForProperty', {name, value});
91 var propertyInfo = DOMProperty.properties.hasOwnProperty(name) ?
92 DOMProperty.properties[name] : null;
93 if (propertyInfo) {
@@ -157,8 +105,6 @@ var DOMPropertyOperations = {
105 return '';
106 }
107 return name + '=' + quoteAttributeValueForBrowser(value);
160 - } else if (__DEV__) {
161 - warnUnknownProperty(name);
108 }
109 return null;
110 },
@@ -185,6 +131,7 @@ var DOMPropertyOperations = {
131 * @param {*} value
132 */
133 setValueForProperty: function(node, name, value) {
134 + ReactDOMDevtools.emitEvent('setValueForProperty', {node, name, value});
135 var propertyInfo = DOMProperty.properties.hasOwnProperty(name) ?
136 DOMProperty.properties[name] : null;
137 if (propertyInfo) {
@@ -219,8 +166,6 @@ var DOMPropertyOperations = {
166 }
167 } else if (DOMProperty.isCustomAttribute(name)) {
168 DOMPropertyOperations.setValueForAttribute(node, name, value);
222 - } else if (__DEV__) {
223 - warnUnknownProperty(name);
169 }
170 },
171
@@ -242,6 +187,7 @@ var DOMPropertyOperations = {
187 * @param {string} name
188 */
189 deleteValueForProperty: function(node, name) {
190 + ReactDOMDevtools.emitEvent('deleteValueForProperty', {node, name});
191 var propertyInfo = DOMProperty.properties.hasOwnProperty(name) ?
192 DOMProperty.properties[name] : null;
193 if (propertyInfo) {
@@ -263,8 +209,6 @@ var DOMPropertyOperations = {
209 }
210 } else if (DOMProperty.isCustomAttribute(name)) {
211 node.removeAttribute(name);
266 - } else if (__DEV__) {
267 - warnUnknownProperty(name);
212 }
213 },
214
src/renderers/dom/shared/__tests__/DOMPropertyOperations-test.js
-35
@@ -50,41 +50,6 @@ describe('DOMPropertyOperations', function() {
50 )).toBe('id="simple"');
51 });
52
53 - it('should warn about incorrect casing on properties', function() {
54 - spyOn(console, 'error');
55 - expect(DOMPropertyOperations.createMarkupForProperty(
56 - 'tabindex',
57 - '1'
58 - )).toBe(null);
59 - expect(console.error.argsForCall.length).toBe(1);
60 - expect(console.error.argsForCall[0][0]).toContain('tabIndex');
61 - });
62 -
63 - it('should warn about incorrect casing on event handlers', function() {
64 - spyOn(console, 'error');
65 - expect(DOMPropertyOperations.createMarkupForProperty(
66 - 'onclick',
67 - '1'
68 - )).toBe(null);
69 - expect(DOMPropertyOperations.createMarkupForProperty(
70 - 'onKeydown',
71 - '1'
72 - )).toBe(null);
73 - expect(console.error.argsForCall.length).toBe(2);
74 - expect(console.error.argsForCall[0][0]).toContain('onClick');
75 - expect(console.error.argsForCall[1][0]).toContain('onKeyDown');
76 - });
77 -
78 - it('should warn about class', function() {
79 - spyOn(console, 'error');
80 - expect(DOMPropertyOperations.createMarkupForProperty(
81 - 'class',
82 - 'muffins'
83 - )).toBe(null);
84 - expect(console.error.argsForCall.length).toBe(1);
85 - expect(console.error.argsForCall[0][0]).toContain('className');
86 - });
87 -
53 it('should create markup for boolean properties', function() {
54 expect(DOMPropertyOperations.createMarkupForProperty(
55 'checked',
src/renderers/dom/shared/__tests__/ReactDOMComponent-test.js
+23
@@ -1087,5 +1087,28 @@ describe('ReactDOMComponent', function() {
1087 'See Link > a > ... > Link > a.'
1088 );
1089 });
1090 +
1091 + it('should warn about incorrect casing on properties', function() {
1092 + spyOn(console, 'error');
1093 + ReactDOMServer.renderToString(React.createElement('input', {type: 'text', tabindex: '1'}));
1094 + expect(console.error.argsForCall.length).toBe(1);
1095 + expect(console.error.argsForCall[0][0]).toContain('tabIndex');
1096 + });
1097 +
1098 + it('should warn about incorrect casing on event handlers', function() {
1099 + spyOn(console, 'error');
1100 + ReactDOMServer.renderToString(React.createElement('input', {type: 'text', onclick: '1'}));
1101 + ReactDOMServer.renderToString(React.createElement('input', {type: 'text', onKeydown: '1'}));
1102 + expect(console.error.argsForCall.length).toBe(2);
1103 + expect(console.error.argsForCall[0][0]).toContain('onClick');
1104 + expect(console.error.argsForCall[1][0]).toContain('onKeyDown');
1105 + });
1106 +
1107 + it('should warn about class', function() {
1108 + spyOn(console, 'error');
1109 + ReactDOMServer.renderToString(React.createElement('div', {class: 'muffins'}));
1110 + expect(console.error.argsForCall.length).toBe(1);
1111 + expect(console.error.argsForCall[0][0]).toContain('className');
1112 + });
1113 });
1114 });
src/renderers/dom/shared/devtools/ReactDOMUnknownPropertyDevtool.js new
+88
@@ -0,0 +1,88 @@
1 +/**
2 + * Copyright 2013-2015, Facebook, Inc.
3 + * All rights reserved.
4 + *
5 + * This source code is licensed under the BSD-style license found in the
6 + * LICENSE file in the root directory of this source tree. An additional grant
7 + * of patent rights can be found in the PATENTS file in the same directory.
8 + *
9 + * @providesModule ReactDOMUnknownPropertyDevtool
10 + */
11 +
12 +'use strict';
13 +
14 +var DOMProperty = require('DOMProperty');
15 +var EventPluginRegistry = require('EventPluginRegistry');
16 +
17 +var warning = require('warning');
18 +
19 +if (__DEV__) {
20 + var reactProps = {
21 + children: true,
22 + dangerouslySetInnerHTML: true,
23 + key: true,
24 + ref: true,
25 + };
26 + var warnedProperties = {};
27 +
28 + var warnUnknownProperty = function(name) {
29 + if (reactProps.hasOwnProperty(name) && reactProps[name] ||
30 + warnedProperties.hasOwnProperty(name) && warnedProperties[name]) {
31 + return;
32 + }
33 +
34 + warnedProperties[name] = true;
35 + var lowerCasedName = name.toLowerCase();
36 +
37 + // data-* attributes should be lowercase; suggest the lowercase version
38 + var standardName = (
39 + DOMProperty.isCustomAttribute(lowerCasedName) ?
40 + lowerCasedName :
41 + DOMProperty.getPossibleStandardName.hasOwnProperty(lowerCasedName) ?
42 + DOMProperty.getPossibleStandardName[lowerCasedName] :
43 + null
44 + );
45 +
46 + // For now, only warn when we have a suggested correction. This prevents
47 + // logging too much when using transferPropsTo.
48 + warning(
49 + standardName == null,
50 + 'Unknown DOM property %s. Did you mean %s?',
51 + name,
52 + standardName
53 + );
54 +
55 + var registrationName = (
56 + EventPluginRegistry.possibleRegistrationNames.hasOwnProperty(
57 + lowerCasedName
58 + ) ?
59 + EventPluginRegistry.possibleRegistrationNames[lowerCasedName] :
60 + null
61 + );
62 +
63 + warning(
64 + registrationName == null,
65 + 'Unknown event handler property %s. Did you mean `%s`?',
66 + name,
67 + registrationName
68 + );
69 + };
70 +}
71 +
72 +class ReactDOMUnknownPropertyDevtool {
73 + handleEvent(eventName, eventData) {
74 + switch (eventName) {
75 + case 'createMarkupForProperty':
76 + case 'setValueForProperty':
77 + case 'deleteValueForProperty':
78 + var name = eventData.name;
79 + if (!DOMProperty.properties.hasOwnProperty(name) &&
80 + !DOMProperty.isCustomAttribute(name)) {
81 + warnUnknownProperty(name);
82 + }
83 + break;
84 + }
85 + }
86 +}
87 +
88 +module.exports = ReactDOMUnknownPropertyDevtool;