From 01cad922109fa44ff1c3d9571117b68561b2cdb4 Mon Sep 17 00:00:00 2001 From: Giuseppe Gurgone Date: Tue, 6 Feb 2018 22:08:34 +0100 Subject: [PATCH 1/2] Sanitize dynamic styles --- src/stylesheet-registry.js | 13 +++++++++++ test/stylesheet-registry.js | 44 +++++++++++++++++++++++++++++++++++-- 2 files changed, 55 insertions(+), 2 deletions(-) diff --git a/src/stylesheet-registry.js b/src/stylesheet-registry.js index 7c8dc969..cdfeeca0 100644 --- a/src/stylesheet-registry.js +++ b/src/stylesheet-registry.js @@ -1,6 +1,7 @@ import hashString from 'string-hash' import DefaultStyleSheet from './lib/stylesheet' +const sanitize = rule => rule.replace(/\/style/g, '\\/style') export default class StyleSheetRegistry { constructor({ styleSheet = null, @@ -13,7 +14,13 @@ export default class StyleSheetRegistry { name: 'styled-jsx', optimizeForSpeed }) + this._sheet.inject() + if (styleSheet && typeof optimizeForSpeed === 'boolean') { + this._sheet.setOptimizeForSpeed(optimizeForSpeed) + this._optimizeForSpeed = this._sheet.isOptimizeForSpeed() + } + this._isBrowser = isBrowser this._fromServer = undefined @@ -146,6 +153,12 @@ export default class StyleSheetRegistry { ) { const cache = {} return function(id, css) { + // Sanitize SSR-ed and client side (style tags) CSS. + // When using optimize for speed we don't need to sanitize + // because we are not inserting markup in the DOM. + if (!this._isBrowser || !this._optimizeForSpeed) { + css = sanitize(css) + } const idcss = id + css if (!cache[idcss]) { cache[idcss] = css.replace(selectoPlaceholderRegexp, id) diff --git a/test/stylesheet-registry.js b/test/stylesheet-registry.js index 1de2c3be..042078ab 100644 --- a/test/stylesheet-registry.js +++ b/test/stylesheet-registry.js @@ -5,7 +5,7 @@ import test from 'ava' import StyleSheetRegistry from '../src/stylesheet-registry' import makeSheet, { invalidRules } from './stylesheet' -function makeRegistry(options) { +function makeRegistry(options = { optimizeForSpeed: true, isBrowser: true }) { const registry = new StyleSheetRegistry({ styleSheet: makeSheet(options), ...options @@ -85,6 +85,44 @@ test('add - filters out invalid rules (index `-1`)', t => { ]) }) +test('add - sanitizes dynamic CSS on the server', t => { + const registry = makeRegistry({ optimizeForSpeed: false, isBrowser: false }) + + registry.add({ + styleId: '123', + css: [ + 'div.__jsx-style-dynamic-selector { color: red }' + ], + dynamic: ['red'] + }) + + t.deepEqual(registry.cssRules(), [ + [ + 'jsx-1871671996', + 'div.jsx-1871671996 { color: red<\\/style> }' + ] + ]) +}) + +test('add - sanitizes dynamic CSS on the client when optimizeForSpeed is false', t => { + const registry = makeRegistry({ optimizeForSpeed: false, isBrowser: true }) + + registry.add({ + styleId: '123', + css: [ + 'div.__jsx-style-dynamic-selector { color: red }' + ], + dynamic: ['red'] + }) + + t.deepEqual(registry.cssRules(), [ + [ + 'jsx-1871671996', + 'div.jsx-1871671996 { color: red<\\/style> }' + ] + ]) +}) + // registry.remove test('remove', t => { @@ -196,7 +234,9 @@ test('createComputeId', t => { // createComputeSelector test('createComputeSelector', t => { - const computeSelector = utilRegistry.createComputeSelector() + const computeSelector = utilRegistry + .createComputeSelector() + .bind(utilRegistry) t.is( computeSelector( From eba796f576494691b008439962da35f1b817fbcc Mon Sep 17 00:00:00 2001 From: Giuseppe Gurgone Date: Wed, 7 Feb 2018 09:26:39 +0100 Subject: [PATCH 2/2] Sanitize only SSR-ed code --- src/stylesheet-registry.js | 8 ++++---- test/stylesheet-registry.js | 19 ------------------- 2 files changed, 4 insertions(+), 23 deletions(-) diff --git a/src/stylesheet-registry.js b/src/stylesheet-registry.js index cdfeeca0..63cf0fd2 100644 --- a/src/stylesheet-registry.js +++ b/src/stylesheet-registry.js @@ -153,10 +153,10 @@ export default class StyleSheetRegistry { ) { const cache = {} return function(id, css) { - // Sanitize SSR-ed and client side (style tags) CSS. - // When using optimize for speed we don't need to sanitize - // because we are not inserting markup in the DOM. - if (!this._isBrowser || !this._optimizeForSpeed) { + // Sanitize SSR-ed CSS. + // Client side code doesn't need to be sanitized since we use + // document.createTextNode (dev) and the CSSOM api sheet.insertRule (prod). + if (!this._isBrowser) { css = sanitize(css) } const idcss = id + css diff --git a/test/stylesheet-registry.js b/test/stylesheet-registry.js index 042078ab..874ece75 100644 --- a/test/stylesheet-registry.js +++ b/test/stylesheet-registry.js @@ -104,25 +104,6 @@ test('add - sanitizes dynamic CSS on the server', t => { ]) }) -test('add - sanitizes dynamic CSS on the client when optimizeForSpeed is false', t => { - const registry = makeRegistry({ optimizeForSpeed: false, isBrowser: true }) - - registry.add({ - styleId: '123', - css: [ - 'div.__jsx-style-dynamic-selector { color: red }' - ], - dynamic: ['red'] - }) - - t.deepEqual(registry.cssRules(), [ - [ - 'jsx-1871671996', - 'div.jsx-1871671996 { color: red<\\/style> }' - ] - ]) -}) - // registry.remove test('remove', t => {