Skip to content

Commit

Permalink
Support React 16 by avoiding CSSPropertyOperation import
Browse files Browse the repository at this point in the history
  • Loading branch information
lelandrichardson committed Nov 9, 2017
1 parent 6dad539 commit 89f67bd
Showing 1 changed file with 124 additions and 3 deletions.
127 changes: 124 additions & 3 deletions src/targets/react-dom.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@
*/
'use strict';

var CSSPropertyOperations = require('react-dom/lib/CSSPropertyOperations');
var Animated = require('../');

// { scale: 2 } => 'scale(2)'
Expand All @@ -19,6 +18,76 @@ function mapTransform(t) {
return `${k}(${t[k]})`;
}

const isUnitlessNumber = {
animationIterationCount: true,
borderImageOutset: true,
borderImageSlice: true,
borderImageWidth: true,
boxFlex: true,
boxFlexGroup: true,
boxOrdinalGroup: true,
columnCount: true,
columns: true,
flex: true,
flexGrow: true,
flexPositive: true,
flexShrink: true,
flexNegative: true,
flexOrder: true,
gridRow: true,
gridRowEnd: true,
gridRowSpan: true,
gridRowStart: true,
gridColumn: true,
gridColumnEnd: true,
gridColumnSpan: true,
gridColumnStart: true,
fontWeight: true,
lineClamp: true,
lineHeight: true,
opacity: true,
order: true,
orphans: true,
tabSize: true,
widows: true,
zIndex: true,
zoom: true,

// SVG-related properties
fillOpacity: true,
floodOpacity: true,
stopOpacity: true,
strokeDasharray: true,
strokeDashoffset: true,
strokeMiterlimit: true,
strokeOpacity: true,
strokeWidth: true,
};

/**
* @param {string} prefix vendor-specific prefix, eg: Webkit
* @param {string} key style name, eg: transitionDuration
* @return {string} style name prefixed with `prefix`, properly camelCased, eg:
* WebkitTransitionDuration
*/
function prefixKey(prefix, key) {
return prefix + key.charAt(0).toUpperCase() + key.substring(1);
}

/**
* Support style names that may come passed in prefixed by adding permutations
* of vendor prefixes.
*/
var prefixes = ['Webkit', 'ms', 'Moz', 'O'];

// Using Object.keys here, or else the vanilla for-in loop makes IE8 go into an
// infinite loop, because it iterates over the newly added props too.
Object.keys(isUnitlessNumber).forEach(function(prop) {
prefixes.forEach(function(prefix) {
isUnitlessNumber[prefixKey(prefix, prop)] = isUnitlessNumber[prop];
});
});

// NOTE(lmr):
// Since this is a hot code path, right now this is mutative...
// As far as I can tell, this shouldn't cause any unexpected behavior.
Expand All @@ -30,11 +99,62 @@ function mapStyle(style) {
return style;
}

function ApplyAnimatedValues(instance, props, comp) {
function dangerousStyleValue(name, value, isCustomProperty) {
// 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
// arbitrary CSS which may be problematic (I couldn't repro this):
// https://www.owasp.org/index.php/XSS_Filter_Evasion_Cheat_Sheet
// http://www.thespanner.co.uk/2007/11/26/ultimate-xss-css-injection/
// This is not an XSS hole but instead a potential CSS injection issue
// which has lead to a greater discussion about how we're going to
// trust URLs moving forward. See #2115901

var isEmpty = value == null || typeof value === 'boolean' || value === '';
if (isEmpty) {
return '';
}

if (
!isCustomProperty &&
typeof value === 'number' &&
value !== 0 &&
!(isUnitlessNumber.hasOwnProperty(name) && isUnitlessNumber[name])
) {
return value + 'px'; // Presumes implicit 'px' suffix for unitless numbers
}

return ('' + value).trim();
}

function setValueForStyles(node, styles) {
var style = node.style;
for (var styleName in styles) {
if (!styles.hasOwnProperty(styleName)) {
continue;
}
var isCustomProperty = styleName.indexOf('--') === 0;
var styleValue = dangerousStyleValue(
styleName,
styles[styleName],
isCustomProperty,
);
if (styleName === 'float') {
styleName = 'cssFloat';
}
if (isCustomProperty) {
style.setProperty(styleName, styleValue);
} else {
style[styleName] = styleValue;
}
}
}

function ApplyAnimatedValues(instance, props) {
if (instance.setNativeProps) {
instance.setNativeProps(props);
} else if (instance.nodeType && instance.setAttribute !== undefined) {
CSSPropertyOperations.setValueForStyles(instance, mapStyle(props.style), comp._reactInternalInstance);
setValueForStyles(instance, mapStyle(props.style));
} else {
return false;
}
Expand All @@ -44,6 +164,7 @@ Animated
.inject
.ApplyAnimatedValues(ApplyAnimatedValues);


module.exports = {
...Animated,
div: Animated.createAnimatedComponent('div'),
Expand Down

0 comments on commit 89f67bd

Please sign in to comment.