Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 | 25x 25x 31x 31x 31x 31x 31x 124x 25x 204x 154x 204x 1558x 1558x 890x 890x 890x 76x 76x 76x 204x 204x 204x 216x 216x 76x 1045x 1045x 1045x 1045x 1030x 690x 690x 36x 36x 36x 36x 690x 1045x 273x 273x 273x 772x 346x 426x 426x 426x 426x 848x 848x 231x 617x 611x 617x 426x 426x 1045x 1045x 1045x 108x 1045x 1045x 1045x 1045x 473x 572x 572x 572x 1698x 1698x 1558x 1558x 1365x 193x 1x 1x 1x 1x 1x 2x 192x 108x 192x 1698x 572x 108x 572x 39x 572x 25x 6x 6x 6x 6x 42x 42x 76x 76x 76x 76x 76x 76x 42x 2x 20x 512x 512x 1045x | /**
* Copyright (c) Nicolas Gallagher.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @noflow
*/
/**
* WARNING: changes to this file in particular can cause significant changes to
* the results of render performance benchmarks.
*/
import { canUseDOM } from 'fbjs/lib/ExecutionEnvironment';
import createCSSStyleSheet from './createCSSStyleSheet';
import createCompileableStyle from './createCompileableStyle';
import createOrderedCSSStyleSheet from './createOrderedCSSStyleSheet';
import flattenArray from '../../modules/flattenArray';
import flattenStyle from './flattenStyle';
import I18nManager from '../I18nManager';
import i18nStyle from './i18nStyle';
import { atomic, classic, inline, stringifyValueWithProperty } from './compile';
import initialRules from './initialRules';
import modality from './modality';
import { STYLE_ELEMENT_ID, STYLE_GROUPS } from './constants';
export default function createStyleResolver() {
let inserted, sheet, cache;
const resolved = { css: {}, ltr: {}, rtl: {}, rtlNoSwap: {} };
const init = () => {
inserted = { css: {}, ltr: {}, rtl: {}, rtlNoSwap: {} };
sheet = createOrderedCSSStyleSheet(createCSSStyleSheet(STYLE_ELEMENT_ID));
cache = {};
modality((rule) => sheet.insert(rule, STYLE_GROUPS.modality));
initialRules.forEach((rule) => {
sheet.insert(rule, STYLE_GROUPS.reset);
});
};
init();
function addToCache(className, prop, value) {
if (!cache[prop]) {
cache[prop] = {};
}
cache[prop][value] = className;
}
function getClassName(prop, value) {
const val = stringifyValueWithProperty(value, prop);
return cache[prop] && cache[prop].hasOwnProperty(val) && cache[prop][val];
}
function _injectRegisteredStyle(id) {
const { doLeftAndRightSwapInRTL, isRTL } = I18nManager.getConstants();
const dir = isRTL ? (doLeftAndRightSwapInRTL ? 'rtl' : 'rtlNoSwap') : 'ltr';
if (!inserted[dir][id]) {
const style = createCompileableStyle(i18nStyle(flattenStyle(id)));
const results = atomic(style);
Object.keys(results).forEach((key) => {
const { identifier, property, rules, value } = results[key];
addToCache(identifier, property, value);
rules.forEach((rule) => {
const group = STYLE_GROUPS.custom[property] || STYLE_GROUPS.atomic;
sheet.insert(rule, group);
});
});
inserted[dir][id] = true;
}
}
/**
* Resolves a React Native style object to DOM attributes
*/
function resolve(style, classList) {
const nextClassList = [];
let props = {};
Iif (!style && !classList) {
return props;
}
if (Array.isArray(classList)) {
flattenArray(classList).forEach((identifier) => {
Eif (identifier) {
if (inserted.css[identifier] == null && resolved.css[identifier] != null) {
const item = resolved.css[identifier];
item.rules.forEach((rule) => {
sheet.insert(rule, item.group);
});
inserted.css[identifier] = true;
}
nextClassList.push(identifier);
}
});
}
if (typeof style === 'number') {
// fast and cachable
_injectRegisteredStyle(style);
const key = createCacheKey(style);
props = _resolveStyle(style, key);
} else if (!Array.isArray(style)) {
// resolve a plain RN style object
props = _resolveStyle(style);
} else {
// flatten the style array
// cache resolved props when all styles are registered
// otherwise fallback to resolving
const flatArray = flattenArray(style);
let isArrayOfNumbers = true;
let cacheKey = '';
for (let i = 0; i < flatArray.length; i++) {
const id = flatArray[i];
if (typeof id !== 'number') {
isArrayOfNumbers = false;
} else {
if (isArrayOfNumbers) {
cacheKey += id + '-';
}
_injectRegisteredStyle(id);
}
}
const key = isArrayOfNumbers ? createCacheKey(cacheKey) : null;
props = _resolveStyle(flatArray, key);
}
nextClassList.push(...props.classList);
const finalProps = {
className: classListToString(nextClassList),
classList: nextClassList
};
if (props.style) {
finalProps.style = props.style;
}
return finalProps;
}
/**
* Resolves a React Native style object
*/
function _resolveStyle(style, key) {
const { doLeftAndRightSwapInRTL, isRTL } = I18nManager.getConstants();
const dir = isRTL ? (doLeftAndRightSwapInRTL ? 'rtl' : 'rtlNoSwap') : 'ltr';
// faster: memoized
if (key != null && resolved[dir][key] != null) {
return resolved[dir][key];
}
const flatStyle = flattenStyle(style);
const localizedStyle = createCompileableStyle(i18nStyle(flatStyle));
// slower: convert style object to props and cache
const props = Object.keys(localizedStyle)
.sort()
.reduce(
(props, styleProp) => {
const value = localizedStyle[styleProp];
if (value != null) {
const className = getClassName(styleProp, value);
if (className) {
props.classList.push(className);
} else {
// Certain properties and values are not transformed by 'createReactDOMStyle' as they
// require more complex transforms into multiple CSS rules. Here we assume that StyleManager
// can bind these styles to a className, and prevent them becoming invalid inline-styles.
if (
styleProp === 'animationKeyframes' ||
styleProp === 'placeholderTextColor' ||
styleProp === 'pointerEvents' ||
styleProp === 'scrollbarWidth'
) {
const a = atomic({ [styleProp]: value });
Object.keys(a).forEach((key) => {
const { identifier, rules } = a[key];
props.classList.push(identifier);
rules.forEach((rule) => {
sheet.insert(rule, STYLE_GROUPS.atomic);
});
});
} else {
if (!props.style) {
props.style = {};
}
// 4x slower render
props.style[styleProp] = value;
}
}
}
return props;
},
{ classList: [] }
);
if (props.style) {
props.style = inline(props.style);
}
if (key != null) {
resolved[dir][key] = props;
}
return props;
}
return {
getStyleSheet() {
const textContent = sheet.getTextContent();
// Reset state on the server so critical css is always the result
Eif (!canUseDOM) {
init();
}
return {
id: STYLE_ELEMENT_ID,
textContent
};
},
createCSS(rules, group) {
const result = {};
Object.keys(rules).forEach((name) => {
const style = rules[name];
const compiled = classic(style, name);
Object.keys(compiled).forEach((key) => {
const { identifier, rules } = compiled[key];
resolved.css[identifier] = { group: group || STYLE_GROUPS.classic, rules };
result[name] = identifier;
});
});
return result;
},
resolve,
get sheet() {
return sheet;
}
};
}
/**
* Misc helpers
*/
const createCacheKey = (id) => {
const prefix = 'rn';
return `${prefix}-${id}`;
};
const classListToString = (list) => list.join(' ').trim();
|