mirror of
https://github.com/zhigang1992/react-native-web.git
synced 2026-03-29 22:42:50 +08:00
Remove dependency on most react-dom internals
This commit is contained in:
@@ -20,7 +20,7 @@ simple `View` without much of React Native's functionality.
|
||||
|
||||
Typical render timings*: mean ± two standard deviations
|
||||
|
||||
| Implementation | Deep tree (ms) | Wide tree (ms) | Tweet (ms) |
|
||||
| Implementation | Deep tree (ms) | Wide tree (ms) | Tweets (ms) |
|
||||
| :--- | ---: | ---: | ---: |
|
||||
| `css-modules` | `87.68` `±13.29` | `171.96` `±14.91` | |
|
||||
| `react-native-web/stylesheet@0.0.81` | `90.59` `±12.03` | `190.37` `±19.65` | |
|
||||
@@ -29,9 +29,10 @@ Typical render timings*: mean ± two standard deviations
|
||||
Other libraries
|
||||
|
||||
| Implementation | Deep tree (ms) | Wide tree (ms) |
|
||||
| `aphrodite@1.2.0` | `101.25` `±18.78` | `224.59` `±22.28` |
|
||||
| :--- | ---: | ---: |
|
||||
| `aphrodite@1.2.0` | `101.25` `±18.78` | `224.59` `±22.28` |
|
||||
| `glamor@3.0.0-1` | `143.39` `±23.05` | `275.21` `±21.10` |
|
||||
| `react-jss@5.4.1 | `142.27` `±16.62` | `318.62` `±26.19` |
|
||||
| `react-jss@5.4.1` | `142.27` `±16.62` | `318.62` `±26.19` |
|
||||
| `reactxp@0.34.3` | `221.36` `±23.35` | `472.61` `±40.86` |
|
||||
| `styled-components@2.0.0-7` | `301.92` `±39.43` | `647.80` `±102.1` |
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
*/
|
||||
|
||||
import invariant from 'fbjs/lib/invariant';
|
||||
import { render } from 'react-dom/lib/ReactMount';
|
||||
import { render } from 'react-dom';
|
||||
import ReactNativeApp from './ReactNativeApp';
|
||||
import StyleSheet from '../../apis/StyleSheet';
|
||||
import React, { Component } from 'react';
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
|
||||
'use strict';
|
||||
|
||||
var TouchHistoryMath = require('react-dom/lib/TouchHistoryMath');
|
||||
var TouchHistoryMath = require('../../vendor/TouchHistoryMath');
|
||||
|
||||
var currentCentroidXOfTouchesChangedAfter = TouchHistoryMath.currentCentroidXOfTouchesChangedAfter;
|
||||
var currentCentroidYOfTouchesChangedAfter = TouchHistoryMath.currentCentroidYOfTouchesChangedAfter;
|
||||
|
||||
@@ -9,8 +9,8 @@
|
||||
|
||||
import { PropTypes } from 'react';
|
||||
import ImageStylePropTypes from '../../components/Image/ImageStylePropTypes';
|
||||
import ReactPropTypeLocations from 'react-dom/lib/ReactPropTypeLocations';
|
||||
import ReactPropTypesSecret from 'react-dom/lib/ReactPropTypesSecret';
|
||||
import ReactPropTypeLocationNames from '../../vendor/ReactPropTypeLocationNames';
|
||||
import ReactPropTypesSecret from '../../vendor/ReactPropTypesSecret';
|
||||
import TextInputStylePropTypes from '../../components/TextInput/TextInputStylePropTypes';
|
||||
import TextStylePropTypes from '../../components/Text/TextStylePropTypes';
|
||||
import ViewStylePropTypes from '../../components/View/ViewStylePropTypes';
|
||||
@@ -29,7 +29,7 @@ class StyleSheetValidation {
|
||||
style,
|
||||
prop,
|
||||
caller,
|
||||
ReactPropTypeLocations.prop,
|
||||
ReactPropTypeLocationNames.prop,
|
||||
null,
|
||||
ReactPropTypesSecret
|
||||
);
|
||||
|
||||
@@ -1,46 +1,4 @@
|
||||
const unitlessNumbers = {
|
||||
animationIterationCount: true,
|
||||
borderImageOutset: true,
|
||||
borderImageSlice: true,
|
||||
borderImageWidth: true,
|
||||
boxFlex: true,
|
||||
boxFlexGroup: true,
|
||||
boxOrdinalGroup: true,
|
||||
columnCount: true,
|
||||
flex: true,
|
||||
flexGrow: true,
|
||||
flexOrder: true,
|
||||
flexPositive: true,
|
||||
flexShrink: true,
|
||||
flexNegative: true,
|
||||
fontWeight: true,
|
||||
gridRow: true,
|
||||
gridColumn: true,
|
||||
lineClamp: true,
|
||||
opacity: true,
|
||||
order: true,
|
||||
orphans: true,
|
||||
tabSize: true,
|
||||
widows: true,
|
||||
zIndex: true,
|
||||
zoom: true,
|
||||
// SVG-related
|
||||
fillOpacity: true,
|
||||
floodOpacity: true,
|
||||
stopOpacity: true,
|
||||
strokeDasharray: true,
|
||||
strokeDashoffset: true,
|
||||
strokeMiterlimit: true,
|
||||
strokeOpacity: true,
|
||||
strokeWidth: true,
|
||||
// transform types
|
||||
scale: true,
|
||||
scaleX: true,
|
||||
scaleY: true,
|
||||
scaleZ: true,
|
||||
// RN properties
|
||||
shadowOpacity: true
|
||||
};
|
||||
import unitlessNumbers from '../../modules/unitlessNumbers';
|
||||
|
||||
const normalizeValue = (property, value) => {
|
||||
if (!unitlessNumbers[property] && typeof value === 'number') {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import CSSPropertyOperations from 'react-dom/lib/CSSPropertyOperations';
|
||||
import requestAnimationFrame from 'fbjs/lib/requestAnimationFrame';
|
||||
import setValueForStyles from '../../vendor/setValueForStyles';
|
||||
|
||||
const getRect = node => {
|
||||
const height = node.offsetHeight;
|
||||
@@ -66,7 +66,7 @@ const UIManager = {
|
||||
const value = props[prop];
|
||||
switch (prop) {
|
||||
case 'style': {
|
||||
CSSPropertyOperations.setValueForStyles(node, value, component._reactInternalInstance);
|
||||
setValueForStyles(node, value, component._reactInternalInstance);
|
||||
break;
|
||||
}
|
||||
case 'class':
|
||||
|
||||
@@ -1,12 +1,11 @@
|
||||
/* eslint-disable */
|
||||
|
||||
/**
|
||||
* Copyright (c) 2015-present, Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
var PooledClass = require('react-dom/lib/PooledClass');
|
||||
var PooledClass = require('../../vendor/PooledClass');
|
||||
|
||||
var twoArgumentPooler = PooledClass.twoArgumentPooler;
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
/* eslint-disable */
|
||||
|
||||
/**
|
||||
* Copyright (c) 2015-present, Facebook, Inc.
|
||||
* All rights reserved.
|
||||
@@ -6,7 +7,7 @@
|
||||
|
||||
'use strict';
|
||||
|
||||
var PooledClass = require('react-dom/lib/PooledClass');
|
||||
var PooledClass = require('../../vendor/PooledClass');
|
||||
|
||||
var twoArgumentPooler = PooledClass.twoArgumentPooler;
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// based on https://github.com/facebook/react/pull/4303/files
|
||||
|
||||
import EventPluginRegistry from 'react-dom/lib/EventPluginRegistry';
|
||||
import EventPluginHub from 'react-dom/lib/EventPluginHub';
|
||||
import normalizeNativeEvent from './normalizeNativeEvent';
|
||||
import ResponderEventPlugin from 'react-dom/lib/ResponderEventPlugin';
|
||||
import ResponderTouchHistoryStore from 'react-dom/lib/ResponderTouchHistoryStore';
|
||||
@@ -49,6 +49,6 @@ ResponderTouchHistoryStore.recordTouchTrack = (topLevelType, nativeEvent) => {
|
||||
originalRecordTouchTrack.call(ResponderTouchHistoryStore, topLevelType, normalizedEvent);
|
||||
};
|
||||
|
||||
EventPluginRegistry.injectEventPluginsByName({
|
||||
EventPluginHub.injection.injectEventPluginsByName({
|
||||
ResponderEventPlugin
|
||||
});
|
||||
|
||||
45
src/modules/unitlessNumbers/index.js
Normal file
45
src/modules/unitlessNumbers/index.js
Normal file
@@ -0,0 +1,45 @@
|
||||
const unitlessNumbers = {
|
||||
animationIterationCount: true,
|
||||
borderImageOutset: true,
|
||||
borderImageSlice: true,
|
||||
borderImageWidth: true,
|
||||
boxFlex: true,
|
||||
boxFlexGroup: true,
|
||||
boxOrdinalGroup: true,
|
||||
columnCount: true,
|
||||
flex: true,
|
||||
flexGrow: true,
|
||||
flexOrder: true,
|
||||
flexPositive: true,
|
||||
flexShrink: true,
|
||||
flexNegative: true,
|
||||
fontWeight: true,
|
||||
gridRow: true,
|
||||
gridColumn: true,
|
||||
lineClamp: true,
|
||||
opacity: true,
|
||||
order: true,
|
||||
orphans: true,
|
||||
tabSize: true,
|
||||
widows: true,
|
||||
zIndex: true,
|
||||
zoom: true,
|
||||
// SVG-related
|
||||
fillOpacity: true,
|
||||
floodOpacity: true,
|
||||
stopOpacity: true,
|
||||
strokeDasharray: true,
|
||||
strokeDashoffset: true,
|
||||
strokeMiterlimit: true,
|
||||
strokeOpacity: true,
|
||||
strokeWidth: true,
|
||||
// transform types
|
||||
scale: true,
|
||||
scaleX: true,
|
||||
scaleY: true,
|
||||
scaleZ: true,
|
||||
// RN properties
|
||||
shadowOpacity: true
|
||||
};
|
||||
|
||||
module.exports = unitlessNumbers;
|
||||
@@ -14,7 +14,7 @@ import { PropTypes } from 'react';
|
||||
|
||||
var colorPropType = function(isRequired, props, propName, componentName, location, propFullName) {
|
||||
var normalizeColor = require('normalize-css-color');
|
||||
var ReactPropTypeLocationNames = require('react-dom/lib/ReactPropTypeLocationNames');
|
||||
var ReactPropTypeLocationNames = require('../vendor/ReactPropTypeLocationNames');
|
||||
var color = props[propName];
|
||||
if (color === undefined || color === null) {
|
||||
if (isRequired) {
|
||||
|
||||
@@ -12,8 +12,8 @@
|
||||
*/
|
||||
|
||||
import invariant from 'fbjs/lib/invariant';
|
||||
import ReactPropTypeLocationNames from 'react-dom/lib/ReactPropTypeLocationNames';
|
||||
import ReactPropTypesSecret from 'react-dom/lib/ReactPropTypesSecret';
|
||||
import ReactPropTypeLocationNames from '../vendor/ReactPropTypeLocationNames';
|
||||
import ReactPropTypesSecret from '../vendor/ReactPropTypesSecret';
|
||||
|
||||
function createStrictShapeTypeChecker(
|
||||
shapeTypes: { [key: string]: ReactPropsCheckType }
|
||||
|
||||
63
src/vendor/PooledClass/index.js
vendored
Normal file
63
src/vendor/PooledClass/index.js
vendored
Normal file
@@ -0,0 +1,63 @@
|
||||
/* eslint-disable */
|
||||
|
||||
/**
|
||||
* Copyright 2013-present, Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the BSD-style license found in the
|
||||
* LICENSE file in the root directory of this source tree. An additional grant
|
||||
* of patent rights can be found in the PATENTS file in the same directory.
|
||||
*/
|
||||
|
||||
var invariant = require('fbjs/lib/invariant');
|
||||
|
||||
var twoArgumentPooler = function(a1, a2) {
|
||||
var Klass = this;
|
||||
if (Klass.instancePool.length) {
|
||||
var instance = Klass.instancePool.pop();
|
||||
Klass.call(instance, a1, a2);
|
||||
return instance;
|
||||
} else {
|
||||
return new Klass(a1, a2);
|
||||
}
|
||||
};
|
||||
|
||||
var standardReleaser = function(instance) {
|
||||
var Klass = this;
|
||||
instance.destructor();
|
||||
if (Klass.instancePool.length < Klass.poolSize) {
|
||||
Klass.instancePool.push(instance);
|
||||
}
|
||||
};
|
||||
|
||||
var DEFAULT_POOL_SIZE = 10;
|
||||
var DEFAULT_POOLER = twoArgumentPooler;
|
||||
|
||||
/**
|
||||
* Augments `CopyConstructor` to be a poolable class, augmenting only the class
|
||||
* itself (statically) not adding any prototypical fields. Any CopyConstructor
|
||||
* you give this may have a `poolSize` property, and will look for a
|
||||
* prototypical `destructor` on instances.
|
||||
*
|
||||
* @param {Function} CopyConstructor Constructor that can be used to reset.
|
||||
* @param {Function} pooler Customizable pooler.
|
||||
*/
|
||||
var addPoolingTo = function(CopyConstructor, pooler) {
|
||||
// Casting as any so that flow ignores the actual implementation and trusts
|
||||
// it to match the type we declared
|
||||
var NewKlass = CopyConstructor;
|
||||
NewKlass.instancePool = [];
|
||||
NewKlass.getPooled = pooler || DEFAULT_POOLER;
|
||||
if (!NewKlass.poolSize) {
|
||||
NewKlass.poolSize = DEFAULT_POOL_SIZE;
|
||||
}
|
||||
NewKlass.release = standardReleaser;
|
||||
return NewKlass;
|
||||
};
|
||||
|
||||
var PooledClass = {
|
||||
addPoolingTo: addPoolingTo,
|
||||
twoArgumentPooler: twoArgumentPooler
|
||||
};
|
||||
|
||||
module.exports = PooledClass;
|
||||
20
src/vendor/ReactPropTypeLocationNames/index.js
vendored
Normal file
20
src/vendor/ReactPropTypeLocationNames/index.js
vendored
Normal file
@@ -0,0 +1,20 @@
|
||||
/**
|
||||
* Copyright 2013-present, Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the BSD-style license found in the
|
||||
* LICENSE file in the root directory of this source tree. An additional grant
|
||||
* of patent rights can be found in the PATENTS file in the same directory.
|
||||
*/
|
||||
|
||||
let ReactPropTypeLocationNames = {};
|
||||
|
||||
if (process.env.NODE_ENV !== 'production') {
|
||||
ReactPropTypeLocationNames = {
|
||||
prop: 'prop',
|
||||
context: 'context',
|
||||
childContext: 'child context'
|
||||
};
|
||||
}
|
||||
|
||||
module.exports = ReactPropTypeLocationNames;
|
||||
10
src/vendor/ReactPropTypesSecret/index.js
vendored
Normal file
10
src/vendor/ReactPropTypesSecret/index.js
vendored
Normal file
@@ -0,0 +1,10 @@
|
||||
/**
|
||||
* Copyright 2013-present, Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the BSD-style license found in the
|
||||
* LICENSE file in the root directory of this source tree. An additional grant
|
||||
* of patent rights can be found in the PATENTS file in the same directory.
|
||||
*/
|
||||
const ReactPropTypesSecret = 'SECRET_DO_NOT_PASS_THIS_OR_YOU_WILL_BE_FIRED';
|
||||
module.exports = ReactPropTypesSecret;
|
||||
122
src/vendor/TouchHistoryMath/index.js
vendored
Normal file
122
src/vendor/TouchHistoryMath/index.js
vendored
Normal file
@@ -0,0 +1,122 @@
|
||||
/* eslint-disable */
|
||||
|
||||
var TouchHistoryMath = {
|
||||
/**
|
||||
* This code is optimized and not intended to look beautiful. This allows
|
||||
* computing of touch centroids that have moved after `touchesChangedAfter`
|
||||
* timeStamp. You can compute the current centroid involving all touches
|
||||
* moves after `touchesChangedAfter`, or you can compute the previous
|
||||
* centroid of all touches that were moved after `touchesChangedAfter`.
|
||||
*
|
||||
* @param {TouchHistoryMath} touchHistory Standard Responder touch track
|
||||
* data.
|
||||
* @param {number} touchesChangedAfter timeStamp after which moved touches
|
||||
* are considered "actively moving" - not just "active".
|
||||
* @param {boolean} isXAxis Consider `x` dimension vs. `y` dimension.
|
||||
* @param {boolean} ofCurrent Compute current centroid for actively moving
|
||||
* touches vs. previous centroid of now actively moving touches.
|
||||
* @return {number} value of centroid in specified dimension.
|
||||
*/
|
||||
centroidDimension: function(touchHistory, touchesChangedAfter, isXAxis, ofCurrent) {
|
||||
var touchBank = touchHistory.touchBank;
|
||||
var total = 0;
|
||||
var count = 0;
|
||||
|
||||
var oneTouchData = touchHistory.numberActiveTouches === 1
|
||||
? touchHistory.touchBank[touchHistory.indexOfSingleActiveTouch]
|
||||
: null;
|
||||
|
||||
if (oneTouchData !== null) {
|
||||
if (oneTouchData.touchActive && oneTouchData.currentTimeStamp > touchesChangedAfter) {
|
||||
total += ofCurrent && isXAxis
|
||||
? oneTouchData.currentPageX
|
||||
: ofCurrent && !isXAxis
|
||||
? oneTouchData.currentPageY
|
||||
: !ofCurrent && isXAxis ? oneTouchData.previousPageX : oneTouchData.previousPageY;
|
||||
count = 1;
|
||||
}
|
||||
} else {
|
||||
for (var i = 0; i < touchBank.length; i++) {
|
||||
var touchTrack = touchBank[i];
|
||||
if (
|
||||
touchTrack !== null &&
|
||||
touchTrack !== undefined &&
|
||||
touchTrack.touchActive &&
|
||||
touchTrack.currentTimeStamp >= touchesChangedAfter
|
||||
) {
|
||||
var toAdd; // Yuck, program temporarily in invalid state.
|
||||
if (ofCurrent && isXAxis) {
|
||||
toAdd = touchTrack.currentPageX;
|
||||
} else if (ofCurrent && !isXAxis) {
|
||||
toAdd = touchTrack.currentPageY;
|
||||
} else if (!ofCurrent && isXAxis) {
|
||||
toAdd = touchTrack.previousPageX;
|
||||
} else {
|
||||
toAdd = touchTrack.previousPageY;
|
||||
}
|
||||
total += toAdd;
|
||||
count++;
|
||||
}
|
||||
}
|
||||
}
|
||||
return count > 0 ? total / count : TouchHistoryMath.noCentroid;
|
||||
},
|
||||
|
||||
currentCentroidXOfTouchesChangedAfter: function(touchHistory, touchesChangedAfter) {
|
||||
return TouchHistoryMath.centroidDimension(
|
||||
touchHistory,
|
||||
touchesChangedAfter,
|
||||
true, // isXAxis
|
||||
true // ofCurrent
|
||||
);
|
||||
},
|
||||
|
||||
currentCentroidYOfTouchesChangedAfter: function(touchHistory, touchesChangedAfter) {
|
||||
return TouchHistoryMath.centroidDimension(
|
||||
touchHistory,
|
||||
touchesChangedAfter,
|
||||
false, // isXAxis
|
||||
true // ofCurrent
|
||||
);
|
||||
},
|
||||
|
||||
previousCentroidXOfTouchesChangedAfter: function(touchHistory, touchesChangedAfter) {
|
||||
return TouchHistoryMath.centroidDimension(
|
||||
touchHistory,
|
||||
touchesChangedAfter,
|
||||
true, // isXAxis
|
||||
false // ofCurrent
|
||||
);
|
||||
},
|
||||
|
||||
previousCentroidYOfTouchesChangedAfter: function(touchHistory, touchesChangedAfter) {
|
||||
return TouchHistoryMath.centroidDimension(
|
||||
touchHistory,
|
||||
touchesChangedAfter,
|
||||
false, // isXAxis
|
||||
false // ofCurrent
|
||||
);
|
||||
},
|
||||
|
||||
currentCentroidX: function(touchHistory) {
|
||||
return TouchHistoryMath.centroidDimension(
|
||||
touchHistory,
|
||||
0, // touchesChangedAfter
|
||||
true, // isXAxis
|
||||
true // ofCurrent
|
||||
);
|
||||
},
|
||||
|
||||
currentCentroidY: function(touchHistory) {
|
||||
return TouchHistoryMath.centroidDimension(
|
||||
touchHistory,
|
||||
0, // touchesChangedAfter
|
||||
false, // isXAxis
|
||||
true // ofCurrent
|
||||
);
|
||||
},
|
||||
|
||||
noCentroid: -1
|
||||
};
|
||||
|
||||
module.exports = TouchHistoryMath;
|
||||
236
src/vendor/setValueForStyles/index.js
vendored
Normal file
236
src/vendor/setValueForStyles/index.js
vendored
Normal file
@@ -0,0 +1,236 @@
|
||||
/* eslint-disable */
|
||||
|
||||
/**
|
||||
* Copyright 2013-present, Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the BSD-style license found in the
|
||||
* LICENSE file in the root directory of this source tree. An additional grant
|
||||
* of patent rights can be found in the PATENTS file in the same directory.
|
||||
*
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
import unitlessNumbers from '../../modules/unitlessNumbers';
|
||||
|
||||
if (process.env.NODE_ENV !== 'production') {
|
||||
var camelizeStyleName = require('fbjs/lib/camelizeStyleName');
|
||||
var warning = require('fbjs/lib/warning');
|
||||
|
||||
// 'msTransform' is correct, but the other prefixes should be capitalized
|
||||
var badVendoredStyleNamePattern = /^(?:webkit|moz|o)[A-Z]/;
|
||||
|
||||
// style values shouldn't contain a semicolon
|
||||
var badStyleValueWithSemicolonPattern = /;\s*$/;
|
||||
|
||||
var warnedStyleNames = {};
|
||||
var warnedStyleValues = {};
|
||||
var warnedForNaNValue = false;
|
||||
|
||||
var warnHyphenatedStyleName = function(name, owner) {
|
||||
if (warnedStyleNames.hasOwnProperty(name) && warnedStyleNames[name]) {
|
||||
return;
|
||||
}
|
||||
|
||||
warnedStyleNames[name] = true;
|
||||
process.env.NODE_ENV !== 'production'
|
||||
? warning(
|
||||
false,
|
||||
'Unsupported style property %s. Did you mean %s?%s',
|
||||
name,
|
||||
camelizeStyleName(name),
|
||||
checkRenderMessage(owner)
|
||||
)
|
||||
: void 0;
|
||||
};
|
||||
|
||||
var warnBadVendoredStyleName = function(name, owner) {
|
||||
if (warnedStyleNames.hasOwnProperty(name) && warnedStyleNames[name]) {
|
||||
return;
|
||||
}
|
||||
|
||||
warnedStyleNames[name] = true;
|
||||
process.env.NODE_ENV !== 'production'
|
||||
? warning(
|
||||
false,
|
||||
'Unsupported vendor-prefixed style property %s. Did you mean %s?%s',
|
||||
name,
|
||||
name.charAt(0).toUpperCase() + name.slice(1),
|
||||
checkRenderMessage(owner)
|
||||
)
|
||||
: void 0;
|
||||
};
|
||||
|
||||
var warnStyleValueWithSemicolon = function(name, value, owner) {
|
||||
if (warnedStyleValues.hasOwnProperty(value) && warnedStyleValues[value]) {
|
||||
return;
|
||||
}
|
||||
|
||||
warnedStyleValues[value] = true;
|
||||
process.env.NODE_ENV !== 'production'
|
||||
? warning(
|
||||
false,
|
||||
"Style property values shouldn't contain a semicolon.%s " + 'Try "%s: %s" instead.',
|
||||
checkRenderMessage(owner),
|
||||
name,
|
||||
value.replace(badStyleValueWithSemicolonPattern, '')
|
||||
)
|
||||
: void 0;
|
||||
};
|
||||
|
||||
var warnStyleValueIsNaN = function(name, value, owner) {
|
||||
if (warnedForNaNValue) {
|
||||
return;
|
||||
}
|
||||
|
||||
warnedForNaNValue = true;
|
||||
process.env.NODE_ENV !== 'production'
|
||||
? warning(
|
||||
false,
|
||||
'`NaN` is an invalid value for the `%s` css style property.%s',
|
||||
name,
|
||||
checkRenderMessage(owner)
|
||||
)
|
||||
: void 0;
|
||||
};
|
||||
|
||||
var checkRenderMessage = function(owner) {
|
||||
if (owner) {
|
||||
var name = owner.getName();
|
||||
if (name) {
|
||||
return ' Check the render method of `' + name + '`.';
|
||||
}
|
||||
}
|
||||
return '';
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {string} name
|
||||
* @param {*} value
|
||||
* @param {ReactDOMComponent} component
|
||||
*/
|
||||
var warnValidStyle = function(name, value, component) {
|
||||
var owner;
|
||||
if (component) {
|
||||
owner = component._currentElement._owner;
|
||||
}
|
||||
if (name.indexOf('-') > -1) {
|
||||
warnHyphenatedStyleName(name, owner);
|
||||
} else if (badVendoredStyleNamePattern.test(name)) {
|
||||
warnBadVendoredStyleName(name, owner);
|
||||
} else if (badStyleValueWithSemicolonPattern.test(value)) {
|
||||
warnStyleValueWithSemicolon(name, value, owner);
|
||||
}
|
||||
|
||||
if (typeof value === 'number' && isNaN(value)) {
|
||||
warnStyleValueIsNaN(name, value, owner);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
var styleWarnings = {};
|
||||
|
||||
/**
|
||||
* Convert a value into the proper css writable value. The style name `name`
|
||||
* should be logical (no hyphens)
|
||||
*
|
||||
* @param {string} name CSS property name such as `topMargin`.
|
||||
* @param {*} value CSS property value such as `10px`.
|
||||
* @param {ReactDOMComponent} component
|
||||
* @return {string} Normalized style value with dimensions applied.
|
||||
*/
|
||||
function dangerousStyleValue(name, value, component) {
|
||||
// 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 '';
|
||||
}
|
||||
|
||||
var isNonNumeric = isNaN(value);
|
||||
if (
|
||||
isNonNumeric || value === 0 || (unitlessNumbers.hasOwnProperty(name) && unitlessNumbers[name])
|
||||
) {
|
||||
return '' + value; // cast to string
|
||||
}
|
||||
|
||||
if (typeof value === 'string') {
|
||||
if (process.env.NODE_ENV !== 'production') {
|
||||
var warning = require('fbjs/lib/warning');
|
||||
|
||||
// Allow '0' to pass through without warning. 0 is already special and
|
||||
// doesn't require units, so we don't need to warn about it.
|
||||
if (component && value !== '0') {
|
||||
var owner = component._currentElement._owner;
|
||||
var ownerName = owner ? owner.getName() : null;
|
||||
if (ownerName && !styleWarnings[ownerName]) {
|
||||
styleWarnings[ownerName] = {};
|
||||
}
|
||||
var warned = false;
|
||||
if (ownerName) {
|
||||
var warnings = styleWarnings[ownerName];
|
||||
warned = warnings[name];
|
||||
if (!warned) {
|
||||
warnings[name] = true;
|
||||
}
|
||||
}
|
||||
if (!warned) {
|
||||
process.env.NODE_ENV !== 'production'
|
||||
? warning(
|
||||
false,
|
||||
'a `%s` tag (owner: `%s`) was passed a numeric string value ' +
|
||||
'for CSS property `%s` (value: `%s`) which will be treated ' +
|
||||
'as a unitless number in a future version of React.',
|
||||
component._currentElement.type,
|
||||
ownerName || 'unknown',
|
||||
name,
|
||||
value
|
||||
)
|
||||
: void 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
value = value.trim();
|
||||
}
|
||||
return value + 'px';
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the value for multiple styles on a node. If a value is specified as
|
||||
* '' (empty string), the corresponding style property will be unset.
|
||||
*
|
||||
* @param {DOMElement} node
|
||||
* @param {object} styles
|
||||
* @param {ReactDOMComponent} component
|
||||
*/
|
||||
const setValueForStyles = function(node, styles, component) {
|
||||
var style = node.style;
|
||||
for (var styleName in styles) {
|
||||
if (!styles.hasOwnProperty(styleName)) {
|
||||
continue;
|
||||
}
|
||||
if (process.env.NODE_ENV !== 'production') {
|
||||
warnValidStyle(styleName, styles[styleName], component);
|
||||
}
|
||||
var styleValue = dangerousStyleValue(styleName, styles[styleName], component);
|
||||
if (styleName === 'float' || styleName === 'cssFloat') {
|
||||
styleName = 'cssFloat';
|
||||
}
|
||||
if (styleValue) {
|
||||
style[styleName] = styleValue;
|
||||
} else {
|
||||
style[styleName] = '';
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
module.exports = setValueForStyles;
|
||||
Reference in New Issue
Block a user