diff --git a/packages/react-strict-dom/src/native/css/index.js b/packages/react-strict-dom/src/native/css/index.js index 1d12d559..f37af5e7 100644 --- a/packages/react-strict-dom/src/native/css/index.js +++ b/packages/react-strict-dom/src/native/css/index.js @@ -158,7 +158,21 @@ function resolveStyle( const stylesToReprocess: { [string]: mixed } = {}; const flatStyle = flattenStyle(style); - for (const propName in flatStyle) { + const symbolKeys = Object.getOwnPropertySymbols(flatStyle); + if (symbolKeys.length > 0) { + for (let i = 0; i < symbolKeys.length; i++) { + const symbolKey = symbolKeys[i]; + const descriptor = Object.getOwnPropertyDescriptor(flatStyle, symbolKey); + if (descriptor != null) { + // Preserve Symbol-keyed values without processing. + Object.defineProperty(result, symbolKey, descriptor); + } + } + } + + const propNames = Object.keys(flatStyle); + for (let i = 0; i < propNames.length; i++) { + const propName = propNames[i]; const styleValue = flatStyle[propName]; // Resolve custom property references @@ -310,7 +324,9 @@ export function props( const flatStyle = resolveStyle(style, options) as $FlowFixMe; - for (const styleProp in flatStyle) { + const styleKeys = Object.keys(flatStyle); + for (let i = 0; i < styleKeys.length; i++) { + const styleProp = styleKeys[i]; const styleValue = flatStyle[styleProp]; // block/inlineSize @@ -486,6 +502,18 @@ export function props( } } + const symbolKeys = Object.getOwnPropertySymbols(flatStyle); + if (symbolKeys.length > 0) { + for (let i = 0; i < symbolKeys.length; i++) { + const symbolKey = symbolKeys[i]; + const descriptor = Object.getOwnPropertyDescriptor(flatStyle, symbolKey); + if (descriptor != null) { + // Preserve Symbol-keyed values without processing. + Object.defineProperty(nextStyle, symbolKey, descriptor); + } + } + } + if (__DEV__) { const displayValue = nextStyle.display; diff --git a/packages/react-strict-dom/src/native/css/processStyle.js b/packages/react-strict-dom/src/native/css/processStyle.js index 70078a1c..7313757c 100644 --- a/packages/react-strict-dom/src/native/css/processStyle.js +++ b/packages/react-strict-dom/src/native/css/processStyle.js @@ -70,7 +70,21 @@ export function processStyle( ): { +[string]: mixed } { const result: { [string]: mixed } = {}; - for (const propName in style) { + const symbolKeys = Object.getOwnPropertySymbols(style); + if (symbolKeys.length > 0) { + for (let i = 0; i < symbolKeys.length; i++) { + const symbolKey = symbolKeys[i]; + const descriptor = Object.getOwnPropertyDescriptor(style, symbolKey); + if (descriptor != null) { + // Preserve Symbol-keyed values without processing. + Object.defineProperty(result, symbolKey, descriptor); + } + } + } + + const propNames = Object.keys(style); + for (let i = 0; i < propNames.length; i++) { + const propName = propNames[i]; const styleValue = style[propName]; if (skipValidation !== true && !isAllowedStyleKey(propName)) { diff --git a/packages/react-strict-dom/tests/css/css-create-test.native.js b/packages/react-strict-dom/tests/css/css-create-test.native.js index 2067238f..a4ae37c0 100644 --- a/packages/react-strict-dom/tests/css/css-create-test.native.js +++ b/packages/react-strict-dom/tests/css/css-create-test.native.js @@ -55,6 +55,24 @@ describe('css.create()', () => { expect(root.toJSON().props.style).toMatchSnapshot(); }); + test('symbol keys are preserved', () => { + const symbolKey = Symbol('raw-style'); + const rawValue = { token: 'raw' }; + const styles = css.create({ + root: { + [symbolKey]: rawValue, + width: '10px' + } + }); + let root; + act(() => { + root = create(); + }); + const renderedStyle = root.toJSON().props.style; + expect(Object.getOwnPropertySymbols(renderedStyle)).toContain(symbolKey); + expect(renderedStyle[symbolKey]).toBe(rawValue); + }); + test('animationName', () => { css.keyframes({ '100%': {