@samitouri / QOS-React-2 / commits / 6c331fba07

Add hasOwnProperty checks where appropriate

For boolean-like objects, I've added hasOwnProperty checks in addition to the existing truthiness check even though for most of these dicts, we leave out false keys instead of setting them explicitly to false. In DOMPropertyOperations, we don't need to check hasOwnProperty if the property is in isStandardName because (with the exception of getPossibleStandardName) the dicts on DOMProperty will now be consistently populated with every valid attribute.

Ben Alpert committed Feb 26, 2014 at 21:13 UTC 6c331fba07d49f05594d6014899e2c95d159b5f2
10 files changed +63 -41
src/addons/transitions/ReactTransitionChildMapping.js
+2 -2
@@ -70,7 +70,7 @@ var ReactTransitionChildMapping = {
70
71 var pendingKeys = [];
72 for (var prevKey in prev) {
73 - if (next[prevKey]) {
73 + if (next.hasOwnProperty(prevKey)) {
74 if (pendingKeys.length) {
75 nextKeysPending[prevKey] = pendingKeys;
76 pendingKeys = [];
@@ -83,7 +83,7 @@ var ReactTransitionChildMapping = {
83 var i;
84 var childMapping = {};
85 for (var nextKey in next) {
86 - if (nextKeysPending[nextKey]) {
86 + if (nextKeysPending.hasOwnProperty(nextKey)) {
87 for (i = 0; i < nextKeysPending[nextKey].length; i++) {
88 var pendingNextKey = nextKeysPending[nextKey][i];
89 childMapping[nextKeysPending[nextKey][i]] = getValueForKey(
src/addons/update.js
+1 -1
@@ -148,7 +148,7 @@ function update(value, spec) {
148 }
149
150 for (var k in spec) {
151 - if (!ALL_COMMANDS_SET[k]) {
151 + if (!(ALL_COMMANDS_SET.hasOwnProperty(k) && ALL_COMMANDS_SET[k])) {
152 nextValue[k] = update(value[k], spec[k]);
153 }
154 }
src/browser/ReactEventEmitter.js
+6 -3
@@ -129,7 +129,7 @@ var topEventMapping = {
129 var topListenersIDKey = "_reactListenersID" + String(Math.random()).slice(2);
130
131 function getListeningForDocument(mountAt) {
132 - if (mountAt[topListenersIDKey] == null) {
132 + if (!mountAt.hasOwnProperty(topListenersIDKey)) {
133 mountAt[topListenersIDKey] = reactTopListenersCounter++;
134 alreadyListeningTo[mountAt[topListenersIDKey]] = {};
135 }
@@ -254,7 +254,10 @@ var ReactEventEmitter = merge(ReactEventEmitterMixin, {
254 var topLevelTypes = EventConstants.topLevelTypes;
255 for (var i = 0, l = dependencies.length; i < l; i++) {
256 var dependency = dependencies[i];
257 - if (!isListening[dependency]) {
257 + if (!(
258 + isListening.hasOwnProperty(dependency) &&
259 + isListening[dependency]
260 + )) {
261 var topLevelType = topLevelTypes[dependency];
262
263 if (topLevelType === topLevelTypes.topWheel) {
@@ -293,7 +296,7 @@ var ReactEventEmitter = merge(ReactEventEmitterMixin, {
296 // to make sure blur and focus event listeners are only attached once
297 isListening[topLevelTypes.topBlur] = true;
298 isListening[topLevelTypes.topFocus] = true;
296 - } else if (topEventMapping[dependency]) {
299 + } else if (topEventMapping.hasOwnProperty(dependency)) {
300 trapBubbledEvent(topLevelType, topEventMapping[dependency], mountAt);
301 }
302
src/browser/eventPlugins/AnalyticsEventPluginFactory.js
+6 -7
@@ -149,19 +149,18 @@ function extractEvents(
149 topLevelTargetID,
150 nativeEvent) {
151 var currentEvent = topLevelTypesToAnalyticsEvent[topLevelType];
152 - if (!currentEvent || !topLevelTarget || !topLevelTarget.attributes) {
152 + if (!currentEvent || !topLevelTarget) {
153 return null;
154 }
155
156 - var analyticsIDAttribute = topLevelTarget.attributes[ANALYTICS_ID];
157 - var analyticsEventsAttribute = topLevelTarget.attributes[ANALYTICS_EVENTS];
158 - if (!analyticsIDAttribute || !analyticsEventsAttribute) {
156 + var analyticsID = topLevelTarget.getAttribute(ANALYTICS_ID);
157 + var analyticsEventsStr = topLevelTarget.getAttribute(ANALYTICS_EVENTS);
158 + if (!analyticsID || !analyticsEventsStr) {
159 return null;
160 }
161
162 - var analyticsEventsArr = analyticsEventsAttribute.value.split(",");
163 - var analyticsID = analyticsIDAttribute.value;
164 - if (!analyticsData[analyticsID]) {
162 + var analyticsEventsArr = analyticsEventsStr.split(",");
163 + if (!analyticsData.hasOwnProperty(analyticsID)) {
164 initAnalyticsDataForID(analyticsID, analyticsEventsArr);
165 }
166
src/browser/ui/ReactDOMComponent.js
+3 -3
@@ -147,7 +147,7 @@ ReactDOMComponent.Mixin = {
147 if (propValue == null) {
148 continue;
149 }
150 - if (registrationNameModules[propKey]) {
150 + if (registrationNameModules.hasOwnProperty(propKey)) {
151 putListener(this._rootNodeID, propKey, propValue, transaction);
152 } else {
153 if (propKey === STYLE) {
@@ -282,7 +282,7 @@ ReactDOMComponent.Mixin = {
282 styleUpdates[styleName] = '';
283 }
284 }
285 - } else if (registrationNameModules[propKey]) {
285 + } else if (registrationNameModules.hasOwnProperty(propKey)) {
286 deleteListener(this._rootNodeID, propKey);
287 } else if (
288 DOMProperty.isStandardName[propKey] ||
@@ -324,7 +324,7 @@ ReactDOMComponent.Mixin = {
324 // Relies on `updateStylesByID` not mutating `styleUpdates`.
325 styleUpdates = nextProp;
326 }
327 - } else if (registrationNameModules[propKey]) {
327 + } else if (registrationNameModules.hasOwnProperty(propKey)) {
328 putListener(this._rootNodeID, propKey, nextProp, transaction);
329 } else if (
330 DOMProperty.isStandardName[propKey] ||
src/browser/ui/dom/DOMProperty.js
+14 -10
@@ -75,7 +75,7 @@ var DOMPropertyInjection = {
75
76 for (var propName in Properties) {
77 invariant(
78 - !DOMProperty.isStandardName[propName],
78 + !DOMProperty.isStandardName.hasOwnProperty(propName),
79 'injectDOMPropertyConfig(...): You\'re trying to inject DOM property ' +
80 '\'%s\' which has already been injected. You may be accidentally ' +
81 'injecting the same DOM property config twice, or you may be ' +
@@ -88,19 +88,23 @@ var DOMPropertyInjection = {
88 var lowerCased = propName.toLowerCase();
89 DOMProperty.getPossibleStandardName[lowerCased] = propName;
90
91 - var attributeName = DOMAttributeNames[propName];
92 - if (attributeName) {
91 + if (DOMAttributeNames.hasOwnProperty(propName)) {
92 + var attributeName = DOMAttributeNames[propName];
93 DOMProperty.getPossibleStandardName[attributeName] = propName;
94 + DOMProperty.getAttributeName[propName] = attributeName;
95 + } else {
96 + DOMProperty.getAttributeName[propName] = lowerCased;
97 }
98
96 - DOMProperty.getAttributeName[propName] = attributeName || lowerCased;
97 -
99 DOMProperty.getPropertyName[propName] =
99 - DOMPropertyNames[propName] || propName;
100 -
101 - var mutationMethod = DOMMutationMethods[propName];
102 - if (mutationMethod) {
103 - DOMProperty.getMutationMethod[propName] = mutationMethod;
100 + DOMPropertyNames.hasOwnProperty(propName) ?
101 + DOMPropertyNames[propName] :
102 + propName;
103 +
104 + if (DOMMutationMethods.hasOwnProperty(propName)) {
105 + DOMProperty.getMutationMethod[propName] = DOMMutationMethods[propName];
106 + } else {
107 + DOMProperty.getMutationMethod[propName] = null;
108 }
109
110 var propConfig = Properties[propName];
src/browser/ui/dom/DOMPropertyOperations.js
+15 -6
@@ -47,7 +47,8 @@ if (__DEV__) {
47 var warnedProperties = {};
48
49 var warnUnknownProperty = function(name) {
50 - if (reactProps[name] || warnedProperties[name]) {
50 + if (reactProps.hasOwnProperty(name) && reactProps[name] ||
51 + warnedProperties.hasOwnProperty(name) && warnedProperties[name]) {
52 return;
53 }
54
@@ -55,8 +56,13 @@ if (__DEV__) {
56 var lowerCasedName = name.toLowerCase();
57
58 // data-* attributes should be lowercase; suggest the lowercase version
58 - var standardName = DOMProperty.isCustomAttribute(lowerCasedName) ?
59 - lowerCasedName : DOMProperty.getPossibleStandardName[lowerCasedName];
59 + var standardName = (
60 + DOMProperty.isCustomAttribute(lowerCasedName) ?
61 + lowerCasedName :
62 + DOMProperty.getPossibleStandardName.hasOwnProperty(lowerCasedName) ?
63 + DOMProperty.getPossibleStandardName[lowerCasedName] :
64 + null
65 + );
66
67 // For now, only warn when we have a suggested correction. This prevents
68 // logging too much when using transferPropsTo.
@@ -92,7 +98,8 @@ var DOMPropertyOperations = {
98 * @return {?string} Markup string, or null if the property was invalid.
99 */
100 createMarkupForProperty: function(name, value) {
95 - if (DOMProperty.isStandardName[name]) {
101 + if (DOMProperty.isStandardName.hasOwnProperty(name) &&
102 + DOMProperty.isStandardName[name]) {
103 if (shouldIgnoreValue(name, value)) {
104 return '';
105 }
@@ -123,7 +130,8 @@ var DOMPropertyOperations = {
130 * @param {*} value
131 */
132 setValueForProperty: function(node, name, value) {
126 - if (DOMProperty.isStandardName[name]) {
133 + if (DOMProperty.isStandardName.hasOwnProperty(name) &&
134 + DOMProperty.isStandardName[name]) {
135 var mutationMethod = DOMProperty.getMutationMethod[name];
136 if (mutationMethod) {
137 mutationMethod(node, value);
@@ -155,7 +163,8 @@ var DOMPropertyOperations = {
163 * @param {string} name
164 */
165 deleteValueForProperty: function(node, name) {
158 - if (DOMProperty.isStandardName[name]) {
166 + if (DOMProperty.isStandardName.hasOwnProperty(name) &&
167 + DOMProperty.isStandardName[name]) {
168 var mutationMethod = DOMProperty.getMutationMethod[name];
169 if (mutationMethod) {
170 mutationMethod(node, undefined);
src/browser/ui/dom/dangerousStyleValue.js
+8 -5
@@ -21,16 +21,18 @@
21
22 var CSSProperty = require('CSSProperty');
23
24 +var isUnitlessNumber = CSSProperty.isUnitlessNumber;
25 +
26 /**
25 - * Convert a value into the proper css writable value. The `styleName` name
26 - * name should be logical (no hyphens), as specified
27 + * Convert a value into the proper css writable value. The style name `name`
28 + * should be logical (no hyphens), as specified
29 * in `CSSProperty.isUnitlessNumber`.
30 *
29 - * @param {string} styleName CSS property name such as `topMargin`.
31 + * @param {string} name CSS property name such as `topMargin`.
32 * @param {*} value CSS property value such as `10px`.
33 * @return {string} Normalized style value with dimensions applied.
34 */
33 -function dangerousStyleValue(styleName, value) {
35 +function dangerousStyleValue(name, value) {
36 // Note that we've removed escapeTextForBrowser() calls here since the
37 // whole string will be escaped when the attribute is injected into
38 // the markup. If you provide unsafe user data here they can inject
@@ -47,7 +49,8 @@ function dangerousStyleValue(styleName, value) {
49 }
50
51 var isNonNumeric = isNaN(value);
50 - if (isNonNumeric || value === 0 || CSSProperty.isUnitlessNumber[styleName]) {
52 + if (isNonNumeric || value === 0 ||
53 + isUnitlessNumber.hasOwnProperty(name) && isUnitlessNumber[name]) {
54 return '' + value; // cast to string
55 }
56
src/core/ReactCompositeComponent.js
+5 -2
@@ -389,7 +389,9 @@ function validateTypeDef(Constructor, typeDef, location) {
389 }
390
391 function validateMethodOverride(proto, name) {
392 - var specPolicy = ReactCompositeComponentInterface[name];
392 + var specPolicy = ReactCompositeComponentInterface.hasOwnProperty(name) ?
393 + ReactCompositeComponentInterface[name] :
394 + null;
395
396 // Disallow overriding of base class methods unless explicitly allowed.
397 if (ReactCompositeComponentMixin.hasOwnProperty(name)) {
@@ -923,7 +925,8 @@ var ReactCompositeComponentMixin = {
925 var props = merge(newProps);
926 var defaultProps = this._defaultProps;
927 for (var propName in defaultProps) {
926 - if (typeof props[propName] === 'undefined') {
928 + if (!props.hasOwnProperty(propName) ||
929 + typeof props[propName] === 'undefined') {
930 props[propName] = defaultProps[propName];
931 }
932 }
src/event/EventPluginRegistry.js
+3 -2
@@ -86,7 +86,7 @@ function recomputePluginOrdering() {
86 */
87 function publishEventForPlugin(dispatchConfig, PluginModule, eventName) {
88 invariant(
89 - !EventPluginRegistry.eventNameDispatchConfigs[eventName],
89 + !EventPluginRegistry.eventNameDispatchConfigs.hasOwnProperty(eventName),
90 'EventPluginHub: More than one plugin attempted to publish the same ' +
91 'event name, `%s`.',
92 eventName
@@ -201,7 +201,8 @@ var EventPluginRegistry = {
201 continue;
202 }
203 var PluginModule = injectedNamesToPlugins[pluginName];
204 - if (namesToPlugins[pluginName] !== PluginModule) {
204 + if (!namesToPlugins.hasOwnProperty(pluginName) ||
205 + namesToPlugins[pluginName] !== PluginModule) {
206 invariant(
207 !namesToPlugins[pluginName],
208 'EventPluginRegistry: Cannot inject two different event plugins ' +