-
Notifications
You must be signed in to change notification settings - Fork 47.3k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Drop "previous style" copy from Stack to bring it inline with Fiber
We've already been warning for mutating styles so now we'll freeze them in DEV instead. This isn't as good because we don't have more specific warnings than the generic error that doesn't even fire in sloppy mode. This lets Fiber pass the same tests.
- Loading branch information
1 parent
9ceed8d
commit 9773577
Showing
4 changed files
with
39 additions
and
125 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -35,7 +35,6 @@ var emptyFunction = require('emptyFunction'); | |
var escapeTextContentForBrowser = require('escapeTextContentForBrowser'); | ||
var invariant = require('invariant'); | ||
var isEventSupported = require('isEventSupported'); | ||
var shallowEqual = require('shallowEqual'); | ||
var inputValueTracking = require('inputValueTracking'); | ||
var validateDOMNesting = require('validateDOMNesting'); | ||
var warning = require('warning'); | ||
|
@@ -74,69 +73,6 @@ function getDeclarationErrorAddendum(internalInstance) { | |
return ''; | ||
} | ||
|
||
function friendlyStringify(obj) { | ||
if (typeof obj === 'object') { | ||
if (Array.isArray(obj)) { | ||
return '[' + obj.map(friendlyStringify).join(', ') + ']'; | ||
} else { | ||
var pairs = []; | ||
for (var key in obj) { | ||
if (Object.prototype.hasOwnProperty.call(obj, key)) { | ||
var keyEscaped = /^[a-z$_][\w$_]*$/i.test(key) ? | ||
key : | ||
JSON.stringify(key); | ||
pairs.push(keyEscaped + ': ' + friendlyStringify(obj[key])); | ||
} | ||
} | ||
return '{' + pairs.join(', ') + '}'; | ||
} | ||
} else if (typeof obj === 'string') { | ||
return JSON.stringify(obj); | ||
} else if (typeof obj === 'function') { | ||
return '[function object]'; | ||
} | ||
// Differs from JSON.stringify in that undefined because undefined and that | ||
// inf and nan don't become null | ||
return String(obj); | ||
} | ||
|
||
var styleMutationWarning = {}; | ||
|
||
function checkAndWarnForMutatedStyle(style1, style2, component) { | ||
if (style1 == null || style2 == null) { | ||
return; | ||
} | ||
if (shallowEqual(style1, style2)) { | ||
return; | ||
} | ||
|
||
var componentName = component._tag; | ||
var owner = component._currentElement._owner; | ||
var ownerName; | ||
if (owner) { | ||
ownerName = owner.getName(); | ||
} | ||
|
||
var hash = ownerName + '|' + componentName; | ||
|
||
if (styleMutationWarning.hasOwnProperty(hash)) { | ||
return; | ||
} | ||
|
||
styleMutationWarning[hash] = true; | ||
|
||
warning( | ||
false, | ||
'`%s` was passed a style object that has previously been mutated. ' + | ||
'Mutating `style` is deprecated. Consider cloning it beforehand. Check ' + | ||
'the `render` %s. Previous style: %s. Mutated style: %s.', | ||
componentName, | ||
owner ? 'of `' + ownerName + '`' : 'using <' + componentName + '>', | ||
friendlyStringify(style1), | ||
friendlyStringify(style2) | ||
); | ||
} | ||
|
||
/** | ||
* @param {object} component | ||
* @param {?object} props | ||
|
@@ -482,8 +418,6 @@ function ReactDOMComponent(element) { | |
this._tag = tag.toLowerCase(); | ||
this._namespaceURI = null; | ||
this._renderedChildren = null; | ||
this._previousStyle = null; | ||
this._previousStyleCopy = null; | ||
this._hostNode = null; | ||
this._hostParent = null; | ||
this._rootNodeID = 0; | ||
|
@@ -763,10 +697,8 @@ ReactDOMComponent.Mixin = { | |
if (propKey === STYLE) { | ||
if (propValue) { | ||
if (__DEV__) { | ||
// See `_updateDOMProperties`. style block | ||
this._previousStyle = propValue; | ||
Object.freeze(propValue); | ||
This comment has been minimized.
Sorry, something went wrong.
This comment has been minimized.
Sorry, something went wrong.
gaearon
Collaborator
|
||
} | ||
propValue = this._previousStyleCopy = Object.assign({}, props.style); | ||
} | ||
propValue = CSSPropertyOperations.createMarkupForStyles(propValue, this); | ||
} | ||
|
@@ -1003,14 +935,13 @@ ReactDOMComponent.Mixin = { | |
continue; | ||
} | ||
if (propKey === STYLE) { | ||
var lastStyle = this._previousStyleCopy; | ||
var lastStyle = lastProps[STYLE]; | ||
for (styleName in lastStyle) { | ||
if (lastStyle.hasOwnProperty(styleName)) { | ||
styleUpdates = styleUpdates || {}; | ||
styleUpdates[styleName] = ''; | ||
} | ||
} | ||
this._previousStyleCopy = null; | ||
} else if (registrationNameModules.hasOwnProperty(propKey)) { | ||
// Do nothing for event names. | ||
} else if (isCustomComponent(this._tag, lastProps)) { | ||
|
@@ -1028,9 +959,7 @@ ReactDOMComponent.Mixin = { | |
} | ||
for (propKey in nextProps) { | ||
var nextProp = nextProps[propKey]; | ||
var lastProp = | ||
propKey === STYLE ? this._previousStyleCopy : | ||
lastProps != null ? lastProps[propKey] : undefined; | ||
var lastProp = lastProps != null ? lastProps[propKey] : undefined; | ||
if (!nextProps.hasOwnProperty(propKey) || | ||
nextProp === lastProp || | ||
nextProp == null && lastProp == null) { | ||
|
@@ -1039,16 +968,8 @@ ReactDOMComponent.Mixin = { | |
if (propKey === STYLE) { | ||
if (nextProp) { | ||
if (__DEV__) { | ||
checkAndWarnForMutatedStyle( | ||
this._previousStyleCopy, | ||
this._previousStyle, | ||
this | ||
); | ||
this._previousStyle = nextProp; | ||
Object.freeze(nextProp); | ||
} | ||
nextProp = this._previousStyleCopy = Object.assign({}, nextProp); | ||
} else { | ||
this._previousStyleCopy = null; | ||
} | ||
if (lastProp) { | ||
// Unset styles on `lastProp` but not on `nextProp`. | ||
|
Hey @sebmarkbage,
I just noticed this change. It causes a runtime error in react-virtualized because I'm temporarily caching
style
objects inGrid
(eg when scrolling) to avoid tripping up theshallowCompare
check. (I manage this caching to prevent user-provided style overrides from recreating style objects on each render.)Unfortunately, certain components (like this) don't take into account that another component (this) is sometimes caching styles. And now that these cached styles are also being frozen, the first component may attempt beaks things when it tries to override a style.
I understand why we want to prevent style object mutation. It surprised me to learn that an object I created (in react-virtualized) was being frozen inside of React though. I wonder if others may have similar issues? Probably not too common a use-case I guess.
Edit: I'll fix this on the react-virtualized side.