Repository: tkh44/emotion (js)

Issue:
Autoprefixer ignores configuration
- `emotion` version: 7.0.11
- `react` version: 16.0.0-alpha.13

Relevant code.

```javascript
const Styled = styled.div`
  display: flex;
`
```

Problem description:
I tried to configure Autoprefixer by setting the Browserslist config in a few ways

 - Using the browserslist key in the package json:
```json
"browserslist": [
  "last 1 Chrome version"
],
``` 

 - Having a .browserslistrc
```
[production]
last 1 Chrome version

[development]
last 1 Chrome version
```

- Setting the BROWSERSLIST environment variable. `BROWSERSLIST="last 1 Chrome version"`

What happened:

Only when setting the env variable did I get the expected result:
```css
.css-1fe3owl {
    display: flex;
}
```

In the other two cases I got:
```css
.css-71uu79 {
    display: -webkit-box;
    display: -ms-flexbox;
    display: flex;
}
```



Pull request description:
Pass filename to PostCSS correctly
Closes #242

<!--
Thanks for your interest in the project. I appreciate bugs filed and PRs submitted!

Please make sure that you are familiar with and follow the Code of Conduct for
this project (found in the CODE_OF_CONDUCT.md file).

Also, please make sure you're familiar with and follow the instructions in the
contributing guidelines (found in the CONTRIBUTING.md file).

If you're new to contributing to open source projects, you might find this free
video course helpful: http://kcd.im/pull-request

Please fill out the information below to expedite the review and (hopefully)
merge of your pull request!
-->

<!-- What changes are being made? (What feature/bug is being fixed here?) -->
**What**:

Pass filename to PostCSS correctly so browserslist can read configs correctly.

<!-- Why are these changes necessary? -->
**Why**:

#242 

<!-- How were these changes implemented? -->
**How**:

For tagged template literals: don't objectify the root node before passing it to the prefixer so that source nodes remain.
For objects: create an `Input` object and set it on the root node before passing it to the prefixer. (it's pretty hacky)

<!-- Have you done all of these things?  -->
**Checklist**:
<!-- add "N/A" to the end of each line that's irrelevant to your changes -->
<!-- to check an item, place an "x" in the box like so: "- [x] Documentation" -->
- [ ] Documentation N/A
- [x] Tests
- [x] Code complete

<!-- feel free to add additional comments -->


Patch:
diff --git a/src/ast-object.js b/src/ast-object.js
index ea613372..7cbbc77c 100644
--- a/src/ast-object.js
+++ b/src/ast-object.js
@@ -1,7 +1,10 @@
+import postcssJs from 'postcss-js'
+import Input from 'postcss/lib/input'
 import { expandCSSFallbacks, prefixer } from './parser'
 import { forEach, reduce } from './utils'
+import { getFilename } from './babel'
 
-function prefixAst(args, t) {
+function prefixAst(args, t, path) {
   function isLiteral(value) {
     return (
       t.isStringLiteral(value) ||
@@ -11,7 +14,7 @@ function prefixAst(args, t) {
   }
 
   if (Array.isArray(args)) {
-    return args.map(element => prefixAst(element, t))
+    return args.map(element => prefixAst(element, t, path))
   }
 
   if (t.isObjectExpression(args)) {
@@ -38,7 +41,7 @@ function prefixAst(args, t) {
           ]
         }
 
-        const prefixedValue = prefixAst(property.value, t)
+        const prefixedValue = prefixAst(property.value, t, path)
 
         if (!property.computed) {
           if (prefixedPseudoSelectors[key.value]) {
@@ -75,7 +78,12 @@ function prefixAst(args, t) {
           : property.value.value
 
         const style = { [property.key.name]: propertyValue }
-        const prefixedStyle = expandCSSFallbacks(prefixer(style))
+        const parsedStyle = postcssJs.parse(style)
+        parsedStyle.source = {}
+        parsedStyle.source.input = new Input(parsedStyle.toString(), {
+          from: getFilename(path)
+        })
+        const prefixedStyle = expandCSSFallbacks(prefixer(parsedStyle))
 
         for (let k in prefixedStyle) {
           const key = t.isStringLiteral(property.key)
@@ -105,7 +113,7 @@ function prefixAst(args, t) {
   }
 
   if (t.isArrayExpression(args)) {
-    return t.arrayExpression(prefixAst(args.elements, t))
+    return t.arrayExpression(prefixAst(args.elements, t, path))
   }
 
   return args
@@ -288,7 +296,7 @@ export default class ASTObject {
     return new ASTObject(props, [], composesCount, t)
   }
 
-  static fromAST(astObj, t) {
+  static fromAST(astObj, t, path) {
     function isLiteral(value) {
       return (
         t.isStringLiteral(value) ||
@@ -376,7 +384,7 @@ export default class ASTObject {
       return props
     }
 
-    const objectProperties = convertAstToObj(prefixAst(astObj, t))
+    const objectProperties = convertAstToObj(prefixAst(astObj, t, path))
     return new ASTObject(
       objectProperties,
       expressions,
diff --git a/src/babel.js b/src/babel.js
index fbfbc979..4a830a1e 100644
--- a/src/babel.js
+++ b/src/babel.js
@@ -16,7 +16,7 @@ import { hashArray } from './hash'
 import cssProps from './css-prop'
 import ASTObject from './ast-object'
 
-function getFilename(path) {
+export function getFilename(path) {
   return path.hub.file.opts.filename === 'unknown'
     ? ''
     : path.hub.file.opts.filename
@@ -203,7 +203,7 @@ export function buildStyledObjectCallExpression(path, state, identifier, t) {
 
 function buildProcessedStylesFromObjectAST(objectAST, path, t) {
   if (t.isObjectExpression(objectAST)) {
-    return ASTObject.fromAST(objectAST, t).toAST()
+    return ASTObject.fromAST(objectAST, t, path).toAST()
   }
   if (t.isArrayExpression(objectAST)) {
     return t.arrayExpression(
diff --git a/src/parser.js b/src/parser.js
index 859f836e..77334030 100644
--- a/src/parser.js
+++ b/src/parser.js
@@ -55,7 +55,7 @@ export function parseCSS(
     }
   })
 
-  const styles = expandCSSFallbacks(prefixer(postcssJs.objectify(root)))
+  const styles = expandCSSFallbacks(prefixer(root))
 
   return {
     styles,


Test patch:
diff --git a/test/__snapshots__/css.test.js.snap b/test/__snapshots__/css.test.js.snap
index 077731ba..7d7a02d9 100644
--- a/test/__snapshots__/css.test.js.snap
+++ b/test/__snapshots__/css.test.js.snap
@@ -17,8 +17,6 @@ exports[`css composes 1`] = `
   display: -webkit-box;
   display: -ms-flexbox;
   display: flex;
-  -webkit-box-pack: center;
-  -ms-flex-pack: center;
   justify-content: center;
 }
 
@@ -35,8 +33,6 @@ exports[`css composes with objects 1`] = `
   display: block;
   width: 30px;
   height: calc(40vw - 50px);
-  -webkit-box-pack: center;
-  -ms-flex-pack: center;
   justify-content: center;
 }
 
@@ -62,8 +58,6 @@ exports[`css composes with objects 1`] = `
 
 exports[`css composes with undefined values 1`] = `
 .glamor-0 {
-  -webkit-box-pack: center;
-  -ms-flex-pack: center;
   justify-content: center;
 }
 
diff --git a/test/babel/__snapshots__/css.test.js.snap b/test/babel/__snapshots__/css.test.js.snap
index 979887fb..a3a9ad18 100644
--- a/test/babel/__snapshots__/css.test.js.snap
+++ b/test/babel/__snapshots__/css.test.js.snap
@@ -58,8 +58,6 @@ const cls1 = css({
 const cls2 = /*#__PURE__*/css([cls1], [], function createEmotionStyledRules() {
   return [{
     'height': '20',
-    'WebkitBoxPack': 'center',
-    'msFlexPack': 'center',
     'justifyContent': 'center'
   }];
 });"
diff --git a/test/babel/css-prop.test.js b/test/babel/css-prop.test.js
index 4185d385..5207eb2f 100644
--- a/test/babel/css-prop.test.js
+++ b/test/babel/css-prop.test.js
@@ -5,6 +5,7 @@ import * as fs from 'fs'
 jest.mock('fs')
 
 fs.existsSync.mockReturnValue(true)
+fs.statSync.mockReturnValue({ isFile: () => false })
 
 describe('babel css prop', () => {
   test('basic with extractStatic', () => {
diff --git a/test/babel/css.test.js b/test/babel/css.test.js
index 1569ec20..c31e83e4 100644
--- a/test/babel/css.test.js
+++ b/test/babel/css.test.js
@@ -4,6 +4,7 @@ import * as fs from 'fs'
 jest.mock('fs')
 
 fs.existsSync.mockReturnValue(true)
+fs.statSync.mockReturnValue({ isFile: () => false })
 
 describe('babel css', () => {
   describe('inline', () => {
diff --git a/test/babel/font-face.test.js b/test/babel/font-face.test.js
index 2684a1b5..ede0c80a 100644
--- a/test/babel/font-face.test.js
+++ b/test/babel/font-face.test.js
@@ -4,6 +4,7 @@ import * as fs from 'fs'
 jest.mock('fs')
 
 fs.existsSync.mockReturnValue(true)
+fs.statSync.mockReturnValue({ isFile: () => false })
 
 describe('fontFace babel', () => {
   describe('inline', () => {
diff --git a/test/babel/fs.test.js b/test/babel/fs.test.js
index 0d6d249e..5282d453 100644
--- a/test/babel/fs.test.js
+++ b/test/babel/fs.test.js
@@ -4,6 +4,7 @@ import touch from 'touch'
 import emotionPlugin from '../../src/babel'
 
 jest.mock('fs').mock('touch')
+fs.statSync.mockReturnValue({ isFile: () => false })
 
 const basic = `
 css\`
diff --git a/test/babel/inject-global.test.js b/test/babel/inject-global.test.js
index 25c30039..823dbe98 100644
--- a/test/babel/inject-global.test.js
+++ b/test/babel/inject-global.test.js
@@ -4,6 +4,7 @@ import * as fs from 'fs'
 jest.mock('fs')
 
 fs.existsSync.mockReturnValue(true)
+fs.statSync.mockReturnValue({ isFile: () => false })
 
 describe('babel injectGlobal', () => {
   describe('inline', () => {
diff --git a/test/babel/keyframes.test.js b/test/babel/keyframes.test.js
index d8ec3422..5f053b20 100644
--- a/test/babel/keyframes.test.js
+++ b/test/babel/keyframes.test.js
@@ -4,6 +4,7 @@ import * as fs from 'fs'
 jest.mock('fs')
 
 fs.existsSync.mockReturnValue(true)
+fs.statSync.mockReturnValue({ isFile: () => false })
 
 describe('babel keyframes', () => {
   describe('inline', () => {
diff --git a/test/babel/styled.test.js b/test/babel/styled.test.js
index d123acef..9f5ed267 100644
--- a/test/babel/styled.test.js
+++ b/test/babel/styled.test.js
@@ -5,6 +5,7 @@ import * as fs from 'fs'
 jest.mock('fs')
 
 fs.existsSync.mockReturnValue(true)
+fs.statSync.mockReturnValue({ isFile: () => false })
 
 describe('babel styled component', () => {
   describe('inline', () => {
diff --git a/test/browserslist/__snapshots__/babel.test.js.snap b/test/browserslist/__snapshots__/babel.test.js.snap
index ed748bd0..301eca58 100644
--- a/test/browserslist/__snapshots__/babel.test.js.snap
+++ b/test/browserslist/__snapshots__/babel.test.js.snap
@@ -4,7 +4,14 @@ exports[`babel css inline css basic 1`] = `
 "
 /*#__PURE__*/css([], [], function createEmotionStyledRules() {
         return [{
-                \\"display\\": \\"-webkit-box; display: -ms-flexbox; display: flex\\"
+                \\"display\\": \\"flex\\"
         }];
 });"
 `;
+
+exports[`babel css inline css object 1`] = `
+"
+css({
+  'display': 'flex'
+});"
+`;
diff --git a/test/browserslist/__snapshots__/css.test.js.snap b/test/browserslist/__snapshots__/css.test.js.snap
index 7704a4a2..2ea9a58c 100644
--- a/test/browserslist/__snapshots__/css.test.js.snap
+++ b/test/browserslist/__snapshots__/css.test.js.snap
@@ -2,8 +2,18 @@
 
 exports[`prefixing css 1`] = `
 .glamor-0 {
-  display: -webkit-box;
-  display: -ms-flexbox;
+  display: flex;
+}
+
+<div
+  className="glamor-0"
+>
+  hello world
+</div>
+`;
+
+exports[`prefixing object 1`] = `
+.glamor-0 {
   display: flex;
 }
 
@@ -16,8 +26,6 @@ exports[`prefixing css 1`] = `
 
 exports[`prefixing styled 1`] = `
 .glamor-1 {
-  display: -webkit-box;
-  display: -ms-flexbox;
   display: flex;
 }
 
diff --git a/test/browserslist/babel.test.js b/test/browserslist/babel.test.js
index 02ac344a..9b7e972c 100644
--- a/test/browserslist/babel.test.js
+++ b/test/browserslist/babel.test.js
@@ -15,5 +15,17 @@ describe('babel css', () => {
       })
       expect(code).toMatchSnapshot()
     })
+    test('css object', () => {
+      const basic = `
+        css({
+          display: 'flex'
+        })`
+      const { code } = babel.transform(basic, {
+        plugins: [[plugin]],
+        filename: __filename,
+        babelrc: false
+      })
+      expect(code).toMatchSnapshot()
+    })
   })
 })
diff --git a/test/browserslist/css.test.js b/test/browserslist/css.test.js
index 5484d095..c5b19bba 100644
--- a/test/browserslist/css.test.js
+++ b/test/browserslist/css.test.js
@@ -23,4 +23,14 @@ describe('prefixing', () => {
 
     expect(tree).toMatchSnapshot()
   })
+  test('object', () => {
+    const cls1 = css({
+      display: 'flex'
+    })
+    const tree = renderer
+      .create(<div className={cls1}>hello world</div>)
+      .toJSON()
+
+    expect(tree).toMatchSnapshot()
+  })
 })
diff --git a/test/macro/__snapshots__/css.test.js.snap b/test/macro/__snapshots__/css.test.js.snap
index 8b4d7e6f..4a54910b 100644
--- a/test/macro/__snapshots__/css.test.js.snap
+++ b/test/macro/__snapshots__/css.test.js.snap
@@ -5,8 +5,6 @@ exports[`css macro composes 1`] = `
   display: -webkit-box;
   display: -ms-flexbox;
   display: flex;
-  -webkit-box-pack: center;
-  -ms-flex-pack: center;
   justify-content: center;
 }
 
@@ -23,8 +21,6 @@ exports[`css macro composes with objects 1`] = `
   display: block;
   width: 30px;
   height: calc(40vw - 50px);
-  -webkit-box-pack: center;
-  -ms-flex-pack: center;
   justify-content: center;
 }
 
@@ -50,8 +46,6 @@ exports[`css macro composes with objects 1`] = `
 
 exports[`css macro composes with undefined values 1`] = `
 .glamor-0 {
-  -webkit-box-pack: center;
-  -ms-flex-pack: center;
   justify-content: center;
 }