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.
This commit is contained in:
Ben Alpert
2014-05-16 10:59:51 -07:00
committed by Paul O’Shannessy
parent c913c95908
commit 6c331fba07
10 changed files with 62 additions and 40 deletions
@@ -70,7 +70,7 @@ var ReactTransitionChildMapping = {
var pendingKeys = [];
for (var prevKey in prev) {
if (next[prevKey]) {
if (next.hasOwnProperty(prevKey)) {
if (pendingKeys.length) {
nextKeysPending[prevKey] = pendingKeys;
pendingKeys = [];
@@ -83,7 +83,7 @@ var ReactTransitionChildMapping = {
var i;
var childMapping = {};
for (var nextKey in next) {
if (nextKeysPending[nextKey]) {
if (nextKeysPending.hasOwnProperty(nextKey)) {
for (i = 0; i < nextKeysPending[nextKey].length; i++) {
var pendingNextKey = nextKeysPending[nextKey][i];
childMapping[nextKeysPending[nextKey][i]] = getValueForKey(
+1 -1
View File
@@ -148,7 +148,7 @@ function update(value, spec) {
}
for (var k in spec) {
if (!ALL_COMMANDS_SET[k]) {
if (!(ALL_COMMANDS_SET.hasOwnProperty(k) && ALL_COMMANDS_SET[k])) {
nextValue[k] = update(value[k], spec[k]);
}
}
+6 -3
View File
@@ -129,7 +129,7 @@ var topEventMapping = {
var topListenersIDKey = "_reactListenersID" + String(Math.random()).slice(2);
function getListeningForDocument(mountAt) {
if (mountAt[topListenersIDKey] == null) {
if (!mountAt.hasOwnProperty(topListenersIDKey)) {
mountAt[topListenersIDKey] = reactTopListenersCounter++;
alreadyListeningTo[mountAt[topListenersIDKey]] = {};
}
@@ -254,7 +254,10 @@ var ReactEventEmitter = merge(ReactEventEmitterMixin, {
var topLevelTypes = EventConstants.topLevelTypes;
for (var i = 0, l = dependencies.length; i < l; i++) {
var dependency = dependencies[i];
if (!isListening[dependency]) {
if (!(
isListening.hasOwnProperty(dependency) &&
isListening[dependency]
)) {
var topLevelType = topLevelTypes[dependency];
if (topLevelType === topLevelTypes.topWheel) {
@@ -293,7 +296,7 @@ var ReactEventEmitter = merge(ReactEventEmitterMixin, {
// to make sure blur and focus event listeners are only attached once
isListening[topLevelTypes.topBlur] = true;
isListening[topLevelTypes.topFocus] = true;
} else if (topEventMapping[dependency]) {
} else if (topEventMapping.hasOwnProperty(dependency)) {
trapBubbledEvent(topLevelType, topEventMapping[dependency], mountAt);
}
@@ -149,19 +149,18 @@ function extractEvents(
topLevelTargetID,
nativeEvent) {
var currentEvent = topLevelTypesToAnalyticsEvent[topLevelType];
if (!currentEvent || !topLevelTarget || !topLevelTarget.attributes) {
if (!currentEvent || !topLevelTarget) {
return null;
}
var analyticsIDAttribute = topLevelTarget.attributes[ANALYTICS_ID];
var analyticsEventsAttribute = topLevelTarget.attributes[ANALYTICS_EVENTS];
if (!analyticsIDAttribute || !analyticsEventsAttribute) {
var analyticsID = topLevelTarget.getAttribute(ANALYTICS_ID);
var analyticsEventsStr = topLevelTarget.getAttribute(ANALYTICS_EVENTS);
if (!analyticsID || !analyticsEventsStr) {
return null;
}
var analyticsEventsArr = analyticsEventsAttribute.value.split(",");
var analyticsID = analyticsIDAttribute.value;
if (!analyticsData[analyticsID]) {
var analyticsEventsArr = analyticsEventsStr.split(",");
if (!analyticsData.hasOwnProperty(analyticsID)) {
initAnalyticsDataForID(analyticsID, analyticsEventsArr);
}
+3 -3
View File
@@ -147,7 +147,7 @@ ReactDOMComponent.Mixin = {
if (propValue == null) {
continue;
}
if (registrationNameModules[propKey]) {
if (registrationNameModules.hasOwnProperty(propKey)) {
putListener(this._rootNodeID, propKey, propValue, transaction);
} else {
if (propKey === STYLE) {
@@ -282,7 +282,7 @@ ReactDOMComponent.Mixin = {
styleUpdates[styleName] = '';
}
}
} else if (registrationNameModules[propKey]) {
} else if (registrationNameModules.hasOwnProperty(propKey)) {
deleteListener(this._rootNodeID, propKey);
} else if (
DOMProperty.isStandardName[propKey] ||
@@ -324,7 +324,7 @@ ReactDOMComponent.Mixin = {
// Relies on `updateStylesByID` not mutating `styleUpdates`.
styleUpdates = nextProp;
}
} else if (registrationNameModules[propKey]) {
} else if (registrationNameModules.hasOwnProperty(propKey)) {
putListener(this._rootNodeID, propKey, nextProp, transaction);
} else if (
DOMProperty.isStandardName[propKey] ||
+13 -9
View File
@@ -75,7 +75,7 @@ var DOMPropertyInjection = {
for (var propName in Properties) {
invariant(
!DOMProperty.isStandardName[propName],
!DOMProperty.isStandardName.hasOwnProperty(propName),
'injectDOMPropertyConfig(...): You\'re trying to inject DOM property ' +
'\'%s\' which has already been injected. You may be accidentally ' +
'injecting the same DOM property config twice, or you may be ' +
@@ -88,19 +88,23 @@ var DOMPropertyInjection = {
var lowerCased = propName.toLowerCase();
DOMProperty.getPossibleStandardName[lowerCased] = propName;
var attributeName = DOMAttributeNames[propName];
if (attributeName) {
if (DOMAttributeNames.hasOwnProperty(propName)) {
var attributeName = DOMAttributeNames[propName];
DOMProperty.getPossibleStandardName[attributeName] = propName;
DOMProperty.getAttributeName[propName] = attributeName;
} else {
DOMProperty.getAttributeName[propName] = lowerCased;
}
DOMProperty.getAttributeName[propName] = attributeName || lowerCased;
DOMProperty.getPropertyName[propName] =
DOMPropertyNames[propName] || propName;
DOMPropertyNames.hasOwnProperty(propName) ?
DOMPropertyNames[propName] :
propName;
var mutationMethod = DOMMutationMethods[propName];
if (mutationMethod) {
DOMProperty.getMutationMethod[propName] = mutationMethod;
if (DOMMutationMethods.hasOwnProperty(propName)) {
DOMProperty.getMutationMethod[propName] = DOMMutationMethods[propName];
} else {
DOMProperty.getMutationMethod[propName] = null;
}
var propConfig = Properties[propName];
+15 -6
View File
@@ -47,7 +47,8 @@ if (__DEV__) {
var warnedProperties = {};
var warnUnknownProperty = function(name) {
if (reactProps[name] || warnedProperties[name]) {
if (reactProps.hasOwnProperty(name) && reactProps[name] ||
warnedProperties.hasOwnProperty(name) && warnedProperties[name]) {
return;
}
@@ -55,8 +56,13 @@ if (__DEV__) {
var lowerCasedName = name.toLowerCase();
// data-* attributes should be lowercase; suggest the lowercase version
var standardName = DOMProperty.isCustomAttribute(lowerCasedName) ?
lowerCasedName : DOMProperty.getPossibleStandardName[lowerCasedName];
var standardName = (
DOMProperty.isCustomAttribute(lowerCasedName) ?
lowerCasedName :
DOMProperty.getPossibleStandardName.hasOwnProperty(lowerCasedName) ?
DOMProperty.getPossibleStandardName[lowerCasedName] :
null
);
// For now, only warn when we have a suggested correction. This prevents
// logging too much when using transferPropsTo.
@@ -92,7 +98,8 @@ var DOMPropertyOperations = {
* @return {?string} Markup string, or null if the property was invalid.
*/
createMarkupForProperty: function(name, value) {
if (DOMProperty.isStandardName[name]) {
if (DOMProperty.isStandardName.hasOwnProperty(name) &&
DOMProperty.isStandardName[name]) {
if (shouldIgnoreValue(name, value)) {
return '';
}
@@ -123,7 +130,8 @@ var DOMPropertyOperations = {
* @param {*} value
*/
setValueForProperty: function(node, name, value) {
if (DOMProperty.isStandardName[name]) {
if (DOMProperty.isStandardName.hasOwnProperty(name) &&
DOMProperty.isStandardName[name]) {
var mutationMethod = DOMProperty.getMutationMethod[name];
if (mutationMethod) {
mutationMethod(node, value);
@@ -155,7 +163,8 @@ var DOMPropertyOperations = {
* @param {string} name
*/
deleteValueForProperty: function(node, name) {
if (DOMProperty.isStandardName[name]) {
if (DOMProperty.isStandardName.hasOwnProperty(name) &&
DOMProperty.isStandardName[name]) {
var mutationMethod = DOMProperty.getMutationMethod[name];
if (mutationMethod) {
mutationMethod(node, undefined);
+8 -5
View File
@@ -21,16 +21,18 @@
var CSSProperty = require('CSSProperty');
var isUnitlessNumber = CSSProperty.isUnitlessNumber;
/**
* Convert a value into the proper css writable value. The `styleName` name
* name should be logical (no hyphens), as specified
* Convert a value into the proper css writable value. The style name `name`
* should be logical (no hyphens), as specified
* in `CSSProperty.isUnitlessNumber`.
*
* @param {string} styleName CSS property name such as `topMargin`.
* @param {string} name CSS property name such as `topMargin`.
* @param {*} value CSS property value such as `10px`.
* @return {string} Normalized style value with dimensions applied.
*/
function dangerousStyleValue(styleName, value) {
function dangerousStyleValue(name, value) {
// Note that we've removed escapeTextForBrowser() calls here since the
// whole string will be escaped when the attribute is injected into
// the markup. If you provide unsafe user data here they can inject
@@ -47,7 +49,8 @@ function dangerousStyleValue(styleName, value) {
}
var isNonNumeric = isNaN(value);
if (isNonNumeric || value === 0 || CSSProperty.isUnitlessNumber[styleName]) {
if (isNonNumeric || value === 0 ||
isUnitlessNumber.hasOwnProperty(name) && isUnitlessNumber[name]) {
return '' + value; // cast to string
}
+5 -2
View File
@@ -389,7 +389,9 @@ function validateTypeDef(Constructor, typeDef, location) {
}
function validateMethodOverride(proto, name) {
var specPolicy = ReactCompositeComponentInterface[name];
var specPolicy = ReactCompositeComponentInterface.hasOwnProperty(name) ?
ReactCompositeComponentInterface[name] :
null;
// Disallow overriding of base class methods unless explicitly allowed.
if (ReactCompositeComponentMixin.hasOwnProperty(name)) {
@@ -923,7 +925,8 @@ var ReactCompositeComponentMixin = {
var props = merge(newProps);
var defaultProps = this._defaultProps;
for (var propName in defaultProps) {
if (typeof props[propName] === 'undefined') {
if (!props.hasOwnProperty(propName) ||
typeof props[propName] === 'undefined') {
props[propName] = defaultProps[propName];
}
}
+3 -2
View File
@@ -86,7 +86,7 @@ function recomputePluginOrdering() {
*/
function publishEventForPlugin(dispatchConfig, PluginModule, eventName) {
invariant(
!EventPluginRegistry.eventNameDispatchConfigs[eventName],
!EventPluginRegistry.eventNameDispatchConfigs.hasOwnProperty(eventName),
'EventPluginHub: More than one plugin attempted to publish the same ' +
'event name, `%s`.',
eventName
@@ -201,7 +201,8 @@ var EventPluginRegistry = {
continue;
}
var PluginModule = injectedNamesToPlugins[pluginName];
if (namesToPlugins[pluginName] !== PluginModule) {
if (!namesToPlugins.hasOwnProperty(pluginName) ||
namesToPlugins[pluginName] !== PluginModule) {
invariant(
!namesToPlugins[pluginName],
'EventPluginRegistry: Cannot inject two different event plugins ' +