Skip to content

Commit

Permalink
Validate babel output against duplicated AST nodes
Browse files Browse the repository at this point in the history
  • Loading branch information
Andarist committed Jun 18, 2018
1 parent a8f4f89 commit 936155b
Show file tree
Hide file tree
Showing 7 changed files with 205 additions and 249 deletions.
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
"@babel/preset-flow": "7.0.0-beta.40",
"@babel/preset-react": "7.0.0-beta.40",
"@babel/preset-stage-0": "7.0.0-beta.40",
"babel-check-duplicated-nodes": "^1.0.0",
"babel-cli": "^6.24.1",
"babel-core": "^6.24.1",
"babel-eslint": "^8.2.3",
Expand Down
3 changes: 2 additions & 1 deletion packages/babel-plugin-emotion/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,8 @@
"touch": "^1.0.0"
},
"devDependencies": {
"@babel/core": "7.0.0-beta.32",
"@babel/core": "7.0.0-beta.40",
"babel-check-duplicated-nodes": "^1.0.0",
"babel-cli": "^6.24.1",
"npm-run-all": "^4.0.2",
"rimraf": "^2.6.1"
Expand Down
9 changes: 7 additions & 2 deletions packages/babel-plugin-emotion/src/babel-utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@ import { hashArray } from './index'
import type { BabelPath, EmotionBabelPluginPass } from './index'
import type { Types, Identifier } from 'babel-flow-types'

function cloneNode(t, node) {
return (typeof t.cloneNode === 'function' ? t.cloneNode : t.cloneDeep)(node)
}

function getDeclaratorName(path: BabelPath, t: Types) {
// $FlowFixMe
const parent = path.findParent(p => p.isVariableDeclarator())
Expand Down Expand Up @@ -54,7 +58,7 @@ export function buildMacroRuntimeNode(
state: EmotionMacroPluginPass,
importName: string,
t: Types
) {
): Identifier {
const runtimeImportPath = getRuntimeImportPath(path, t)
if (state.emotionImports === undefined) state.emotionImports = {}
if (state.emotionImports[runtimeImportPath] === undefined) {
Expand All @@ -66,7 +70,8 @@ export function buildMacroRuntimeNode(
importName
] = path.scope.generateUidIdentifier(path.node.name)
}
return state.emotionImports[runtimeImportPath][importName]
// $FlowFixMe
return cloneNode(t, state.emotionImports[runtimeImportPath][importName])
}

export function addRuntimeImports(state: EmotionMacroPluginPass, t: Types) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -356,7 +356,7 @@ var _emotion = require(\\"emotion\\");
var _react = _interopRequireWildcard(require(\\"react\\"));
function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } }
function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = Object.defineProperty && Object.getOwnPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : {}; if (desc.get || desc.set) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } } newObj.default = obj; return newObj; } }
class Home extends _react.Component {
render() {
Expand Down
35 changes: 32 additions & 3 deletions packages/babel-plugin-emotion/test/macro.test.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
// @flow
import * as babel6 from 'babel-core'
import * as babel7 from '@babel/core'
import checkDuplicatedNodes from 'babel-check-duplicated-nodes'
import { createMacroTests } from './util'

const styledCases = {
Expand Down Expand Up @@ -73,13 +74,13 @@ const cases = {
padding: 0;
& > div {
display: none;
&:hover {
color: green;
& span {
color: red;
&:after {
content: "end of line"
}
Expand Down Expand Up @@ -232,4 +233,32 @@ describe('styled macro', () => {
})
).toThrowError(/the emotion macro must be imported with es modules/)
})

test('inserts unique AST nodes', () => {
const input = `
import { css } from './styled/macro'
const normal = css\`
font-weight: 400;
\`
const demibold = css\`
font-weight: 600;
\`
export { normal, demibold }
`

const { ast } = babel7.transform(input, {
plugins: [
'module:babel-plugin-macros',
'@babel/plugin-transform-modules-commonjs'
],
filename: __filename,
babelrc: false,
ast: true
})

expect(() => checkDuplicatedNodes(babel7, ast)).not.toThrow()
})
})
97 changes: 55 additions & 42 deletions packages/babel-plugin-emotion/test/util.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
// @flow
/* eslint-env jest */
import plugin from 'babel-plugin-emotion'
import { transform as babel6Transform } from 'babel-core'
import { transform as babel7Transform } from '@babel/core'
import * as babel6 from 'babel-core'
import * as babel7 from '@babel/core'
import stage2 from 'babel-plugin-syntax-object-rest-spread'
import makeCases from 'jest-in-case'
import checkDuplicatedNodes from 'babel-check-duplicated-nodes'
import { basename } from 'path'
import * as fs from 'fs'

Expand All @@ -25,38 +26,43 @@ jest.mock('fs')
fs.existsSync.mockReturnValue(true)
fs.statSync.mockReturnValue({ isFile: () => false })

const createInlineTester = transform => opts => {
const isBabel7 = babel => parseInt(babel.version.split('.')[0], 10) === 7

const createInlineTester = babel => opts => {
if (!opts.opts) opts.opts = {}
expect(
transform(opts.code, {
plugins: [
stage2,
[
plugin,
{
...opts.opts
}
]
],
filename: opts.filename !== undefined ? opts.filename : 'emotion.js',
babelrc: false
}).code
).toMatchSnapshot()
const { code, ast } = babel.transform(opts.code, {
plugins: [
stage2,
[
plugin,
{
...opts.opts
}
]
],
filename: opts.filename !== undefined ? opts.filename : 'emotion.js',
babelrc: false,
ast: true
})
if (isBabel7(babel)) {
expect(() => checkDuplicatedNodes(babel, ast)).not.toThrow()
}
expect(code).toMatchSnapshot()
}

export const createInlineTests = (title: string, cases: EmotionTestCases) => {
describe(title, () => {
makeCases('babel 6', createInlineTester(babel6Transform), cases)
makeCases('babel 7', createInlineTester(babel7Transform), cases)
makeCases('babel 6', createInlineTester(babel6), cases)
makeCases('babel 7', createInlineTester(babel7), cases)
})
}

const createExtractTester = transform => opts => {
const createExtractTester = babel => opts => {
fs.writeFileSync.mockClear()
let extract = true
if (opts.extract === false) extract = false
if (!opts.opts) opts.opts = {}
const { code } = transform(opts.code, {
const { code, ast } = babel.transform(opts.code, {
plugins: [
stage2,
[
Expand All @@ -68,8 +74,12 @@ const createExtractTester = transform => opts => {
]
],
filename: opts.filename || 'emotion.js',
babelrc: false
babelrc: false,
ast: true
})
if (isBabel7(babel)) {
expect(() => checkDuplicatedNodes(babel, ast)).not.toThrow()
}
if (extract) {
expect(
code +
Expand All @@ -86,32 +96,35 @@ const createExtractTester = transform => opts => {

export const createExtractTests = (title: string, cases: EmotionTestCases) => {
describe(title, () => {
makeCases('babel 6', createExtractTester(babel6Transform), cases)
makeCases('babel 7', createExtractTester(babel7Transform), cases)
makeCases('babel 6', createExtractTester(babel6), cases)
makeCases('babel 7', createExtractTester(babel7), cases)
})
}

const createMacroTester = transform => opts => {
const createMacroTester = babel => opts => {
if (!opts.opts) opts.opts = {}
expect(
transform(opts.code, {
plugins: [
[
require('babel-plugin-macros'),
{
...opts.opts
}
]
],
babelrc: false,
filename: opts.filename || __filename
}).code
).toMatchSnapshot()
const { code, ast } = babel.transform(opts.code, {
plugins: [
[
require('babel-plugin-macros'),
{
...opts.opts
}
]
],
babelrc: false,
filename: opts.filename || __filename,
ast: true
})
if (isBabel7(babel)) {
expect(() => checkDuplicatedNodes(babel, ast)).not.toThrow()
}
expect(code).toMatchSnapshot()
}

export const createMacroTests = (title: string, cases: EmotionTestCases) => {
describe(title, () => {
makeCases('babel 6', createMacroTester(babel6Transform), cases)
makeCases('babel 7', createMacroTester(babel7Transform), cases)
makeCases('babel 6', createMacroTester(babel6), cases)
makeCases('babel 7', createMacroTester(babel7), cases)
})
}
Loading

0 comments on commit 936155b

Please sign in to comment.