From d018577127703ff1c36ff392f64ad53c35383224 Mon Sep 17 00:00:00 2001 From: Anton Ignatov Date: Sun, 4 Feb 2018 16:24:10 +0300 Subject: [PATCH] Better way to detect dynamic styles (#401) --- src/_utils.js | 19 ++++++++++++++++++- test/__snapshots__/attribute.js.snap | 12 +++++++++++- test/fixtures/attribute-generation-modes.js | 16 ++++++++++++++++ 3 files changed, 45 insertions(+), 2 deletions(-) diff --git a/src/_utils.js b/src/_utils.js index c89025f4..f9a74049 100644 --- a/src/_utils.js +++ b/src/_utils.js @@ -135,7 +135,24 @@ export const validateExpressionVisitor = { return } - if (scope.hasOwnBinding(name) || path.scope.hasOwnBinding(name)) { + let targetScope = path.scope + let isDynamicBinding = false + + // Traversing scope chain in order to find current variable. + // If variable has no parent scope and it's `const` then we can interp. it + // as static in order to optimize styles. + // `let` and `var` can be changed during runtime. + while (targetScope) { + if (targetScope.hasOwnBinding(name)) { + const binding = targetScope.bindings[name] + isDynamicBinding = + binding.scope.parent !== null || binding.kind !== 'const' + break + } + targetScope = targetScope.parent + } + + if (isDynamicBinding) { throw path.buildCodeFrameError( `Expected \`${name}\` ` + `to not come from the closest scope.\n` + diff --git a/test/__snapshots__/attribute.js.snap b/test/__snapshots__/attribute.js.snap index 65aba8f2..eb032a59 100644 --- a/test/__snapshots__/attribute.js.snap +++ b/test/__snapshots__/attribute.js.snap @@ -83,7 +83,17 @@ const foo = 'red'; export const Test10 = () =>

dynamic with constant variable

<_JSXStyle styleId={\\"461505126\\"} css={\`p.jsx-461505126{color:\${foo};}\`} /> -
;" + ; + +// dynamic with complex scope +export const Test11 = ({ color }) => { + const items = Array.from({ length: 5 }).map((item, i) =>
  • + <_JSXStyle styleId={\\"2172653867\\"} css={\`.item.__jsx-style-dynamic-selector{color:\${color};}\`} dynamic={[color]} /> + Item #{i + 1} +
  • ); + + return ; +};" `; exports[`rewrites className 1`] = ` diff --git a/test/fixtures/attribute-generation-modes.js b/test/fixtures/attribute-generation-modes.js index be140f3f..1454a4c3 100644 --- a/test/fixtures/attribute-generation-modes.js +++ b/test/fixtures/attribute-generation-modes.js @@ -148,3 +148,19 @@ export const Test10 = () => ( `} ) + +// dynamic with complex scope +export const Test11 = ({ color }) => { + const items = Array.from({ length: 5 }).map((item, i) => ( +
  • + + Item #{i + 1} +
  • + )) + + return +}