From 539bc0c2acf164b6c31f5df55f05db35932af100 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Burzy=C5=84ski?= Date: Sun, 27 Oct 2019 13:02:18 +0100 Subject: [PATCH] Insert import to @emotion/core after existing imports to avoid ordering issues with polyfills (#1576) --- .changeset/five-ligers-chew.md | 6 ++++ .../__fixtures__/existing-imports.js | 9 ++++++ .../__tests__/__snapshots__/index.js.snap | 28 +++++++++++++++++-- .../babel-plugin-jsx-pragmatic/package.json | 2 +- .../babel-plugin-jsx-pragmatic/src/index.js | 27 ++++++++++++++---- .../__tests__/__snapshots__/index.js.snap | 3 +- .../__snapshots__/options-are-used.js.snap | 3 +- 7 files changed, 65 insertions(+), 13 deletions(-) create mode 100644 .changeset/five-ligers-chew.md create mode 100644 packages/babel-plugin-jsx-pragmatic/__tests__/__fixtures__/existing-imports.js diff --git a/.changeset/five-ligers-chew.md b/.changeset/five-ligers-chew.md new file mode 100644 index 000000000..abe97a4ec --- /dev/null +++ b/.changeset/five-ligers-chew.md @@ -0,0 +1,6 @@ +--- +'@emotion/babel-plugin-jsx-pragmatic': patch +'@emotion/babel-preset-css-prop': patch +--- + +Insert import to @emotion/core after existing imports to avoid ordering issues with polyfills diff --git a/packages/babel-plugin-jsx-pragmatic/__tests__/__fixtures__/existing-imports.js b/packages/babel-plugin-jsx-pragmatic/__tests__/__fixtures__/existing-imports.js new file mode 100644 index 000000000..ab2042627 --- /dev/null +++ b/packages/babel-plugin-jsx-pragmatic/__tests__/__fixtures__/existing-imports.js @@ -0,0 +1,9 @@ +// inserted import has to go AFTER polyfills +import 'react-app-polyfill/ie11' +import 'react-app-polyfill/stable' + +import React from 'react' +import ReactDOM from 'react-dom' +import App from './App' + +ReactDOM.render(, document.getElementById('root')) diff --git a/packages/babel-plugin-jsx-pragmatic/__tests__/__snapshots__/index.js.snap b/packages/babel-plugin-jsx-pragmatic/__tests__/__snapshots__/index.js.snap index 2eeba94e4..8a22e108f 100644 --- a/packages/babel-plugin-jsx-pragmatic/__tests__/__snapshots__/index.js.snap +++ b/packages/babel-plugin-jsx-pragmatic/__tests__/__snapshots__/index.js.snap @@ -1,5 +1,29 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP +exports[`@emotion/babel-plugin-jsx-pragmatic existing-imports 1`] = ` +"// inserted import has to go AFTER polyfills +import 'react-app-polyfill/ie11' +import 'react-app-polyfill/stable' + +import React from 'react' +import ReactDOM from 'react-dom' +import App from './App' + +ReactDOM.render(, document.getElementById('root')) + + + ↓ ↓ ↓ ↓ ↓ ↓ + +// inserted import has to go AFTER polyfills +import 'react-app-polyfill/ie11'; +import 'react-app-polyfill/stable'; +import React from 'react'; +import ReactDOM from 'react-dom'; +import App from './App'; +import { jsx as ___EmotionJSX } from \\"@emotion/core\\"; +ReactDOM.render(, document.getElementById('root'));" +`; + exports[`@emotion/babel-plugin-jsx-pragmatic fragment-only 1`] = ` "import * as React from 'react' @@ -8,8 +32,8 @@ const F = () => <> ↓ ↓ ↓ ↓ ↓ ↓ -import { jsx as ___EmotionJSX } from \\"@emotion/core\\"; import * as React from 'react'; +import { jsx as ___EmotionJSX } from \\"@emotion/core\\"; const F = () => <>;" `; @@ -22,8 +46,8 @@ const P = () =>

↓ ↓ ↓ ↓ ↓ ↓ -import { jsx as ___EmotionJSX } from \\"@emotion/core\\"; import * as React from 'react'; +import { jsx as ___EmotionJSX } from \\"@emotion/core\\"; const P = () =>

;" `; diff --git a/packages/babel-plugin-jsx-pragmatic/package.json b/packages/babel-plugin-jsx-pragmatic/package.json index e0fef248b..ca41b830c 100644 --- a/packages/babel-plugin-jsx-pragmatic/package.json +++ b/packages/babel-plugin-jsx-pragmatic/package.json @@ -22,4 +22,4 @@ "devDependencies": { "@babel/core": "^7.5.5" } -} \ No newline at end of file +} diff --git a/packages/babel-plugin-jsx-pragmatic/src/index.js b/packages/babel-plugin-jsx-pragmatic/src/index.js index 4c92452b7..2b1fbb44f 100644 --- a/packages/babel-plugin-jsx-pragmatic/src/index.js +++ b/packages/babel-plugin-jsx-pragmatic/src/index.js @@ -1,9 +1,18 @@ import syntaxJsx from '@babel/plugin-syntax-jsx' +const findLast = (arr, predicate) => { + for (let i = arr.length - 1; i >= 0; i--) { + if (predicate(arr[i])) { + return arr[i] + } + } +} + export default function jsxPragmatic(babel) { const t = babel.types - function getPragmaImport(state) { - return t.importDeclaration( + + function addPragmaImport(path, state) { + const importDeclar = t.importDeclaration( [ t.importSpecifier( t.identifier(state.opts.import), @@ -12,6 +21,15 @@ export default function jsxPragmatic(babel) { ], t.stringLiteral(state.opts.module) ) + + const targetPath = findLast(path.get('body'), p => p.isImportDeclaration()) + + if (targetPath) { + targetPath.insertAfter([importDeclar]) + } else { + // Apparently it's now safe to do this even if Program begins with directives. + path.unshiftContainer('body', importDeclar) + } } return { @@ -27,10 +45,7 @@ export default function jsxPragmatic(babel) { Program: { exit: function(path, state) { if (!state.get('jsxDetected')) return - - // Apparently it's now safe to do this even if Program begins with - // directives. - path.unshiftContainer('body', getPragmaImport(state)) + addPragmaImport(path, state) } }, diff --git a/packages/babel-preset-css-prop/__tests__/__snapshots__/index.js.snap b/packages/babel-preset-css-prop/__tests__/__snapshots__/index.js.snap index 404309955..385243dd8 100644 --- a/packages/babel-preset-css-prop/__tests__/__snapshots__/index.js.snap +++ b/packages/babel-preset-css-prop/__tests__/__snapshots__/index.js.snap @@ -19,13 +19,12 @@ export let Button = props => { ↓ ↓ ↓ ↓ ↓ ↓ -import { jsx as ___EmotionJSX } from \\"@emotion/core\\"; - function _extends() { _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); } function _EMOTION_STRINGIFIED_CSS_ERROR__() { return \\"You have tried to stringify object returned from \`css\` function. It isn't supposed to be used directly (e.g. as value of the \`className\` prop), but rather handed to emotion so it can handle it (e.g. as value of \`css\` prop).\\"; } import * as React from 'react'; +import { jsx as ___EmotionJSX } from \\"@emotion/core\\"; var _ref = process.env.NODE_ENV === \\"production\\" ? { name: \\"1q24rv0-Button\\", diff --git a/packages/babel-preset-css-prop/__tests__/__snapshots__/options-are-used.js.snap b/packages/babel-preset-css-prop/__tests__/__snapshots__/options-are-used.js.snap index 07b6c5169..3b783f381 100644 --- a/packages/babel-preset-css-prop/__tests__/__snapshots__/options-are-used.js.snap +++ b/packages/babel-preset-css-prop/__tests__/__snapshots__/options-are-used.js.snap @@ -19,11 +19,10 @@ export let Button = props => { ↓ ↓ ↓ ↓ ↓ ↓ -import { jsx as ___EmotionJSX } from \\"@emotion/core\\"; - function _extends() { _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); } import * as React from 'react'; +import { jsx as ___EmotionJSX } from \\"@emotion/core\\"; var _ref = { name: \\"1a7y9g-__fixtures__--__fixtures__--Button\\", styles: \\"color:hotpink;;label:__fixtures__--__fixtures__--Button;\\"