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 ' +