Browse Source

feat(compiler): include names in source map

Evan You 6 years ago
parent
commit
3bba461128

+ 43 - 0
packages/compiler-core/__tests__/__snapshots__/compile.spec.ts.snap

@@ -21,6 +21,25 @@ return function render() {
 }"
 `;
 
+exports[`compiler: integration tests function mode 2`] = `
+Object {
+  "mappings": ";;;;WAAA,oBAAA;MAAK,IAAG;MAAO,OAAO;;gBACpB;MACW;UAAX,uBAAe;UACE;MACjB,YAA8B,OAAjB,OAAO;eAApB,wBAAoC,kCAAM",
+  "names": Array [],
+  "sources": Array [
+    "foo.vue",
+  ],
+  "sourcesContent": Array [
+    "<div id=\\"foo\\" :class=\\"bar\\">
+  {{ world }}
+  <div v-if=\\"ok\\">yes</div>
+  <template v-else>no</template>
+  <div v-for=\\"(value, index) in list\\"><span>{{ value + index }}</span></div>
+</div>",
+  ],
+  "version": 3,
+}
+`;
+
 exports[`compiler: integration tests function mode w/ prefixIdentifiers: true 1`] = `
 "const { createVNode, toString, renderList } = Vue
 
@@ -41,6 +60,30 @@ return function render() {
 }"
 `;
 
+exports[`compiler: integration tests function mode w/ prefixIdentifiers: true 2`] = `
+Object {
+  "mappings": ";;;;SAAA,mBAAA;IAAK,IAAG;IAAO,OAAOA;;aACpBC;KACWC;QAAX,sBAAe;QACE;IACjB,WAA8BC,YAAjB,OAAO;aAApB,uBAAoC,gCAAS,QAAQ",
+  "names": Array [
+    "bar",
+    "world",
+    "ok",
+    "list",
+  ],
+  "sources": Array [
+    "foo.vue",
+  ],
+  "sourcesContent": Array [
+    "<div id=\\"foo\\" :class=\\"bar\\">
+  {{ world }}
+  <div v-if=\\"ok\\">yes</div>
+  <template v-else>no</template>
+  <div v-for=\\"(value, index) in list\\"><span>{{ value + index }}</span></div>
+</div>",
+  ],
+  "version": 3,
+}
+`;
+
 exports[`compiler: integration tests module mode 1`] = `
 "import { createVNode, toString, renderList } from \\"vue\\"
 

+ 42 - 22
packages/compiler-core/__tests__/compile.spec.ts

@@ -11,7 +11,17 @@ describe('compiler: integration tests', () => {
 </div>
 `.trim()
 
-  function getPositionInCode(code: string, token: string) {
+  interface Pos {
+    line: number
+    column: number
+    name?: string
+  }
+
+  function getPositionInCode(
+    code: string,
+    token: string,
+    expectName: string | boolean = false
+  ): Pos {
     const generatedOffset = code.indexOf(token)
     let line = 1
     let lastNewLinePos = -1
@@ -21,13 +31,17 @@ describe('compiler: integration tests', () => {
         lastNewLinePos = i
       }
     }
-    return {
+    const res: Pos = {
       line,
       column:
         lastNewLinePos === -1
           ? generatedOffset
           : generatedOffset - lastNewLinePos - 1
     }
+    if (expectName) {
+      res.name = typeof expectName === 'string' ? expectName : token
+    }
+    return res
   }
 
   test('function mode', async () => {
@@ -41,6 +55,7 @@ describe('compiler: integration tests', () => {
     )
 
     expect(code).toMatchSnapshot()
+    expect(map).toMatchSnapshot()
     expect(map!.sources).toEqual([`foo.vue`])
     expect(map!.sourcesContent).toEqual([source])
 
@@ -97,6 +112,7 @@ describe('compiler: integration tests', () => {
     expect(code).toMatch(`const { createVNode, toString, renderList } = Vue`)
 
     expect(code).toMatchSnapshot()
+    expect(map).toMatchSnapshot()
     expect(map!.sources).toEqual([`foo.vue`])
     expect(map!.sourcesContent).toEqual([source])
 
@@ -118,29 +134,31 @@ describe('compiler: integration tests', () => {
       consumer.originalPositionFor(getPositionInCode(code, `bar`))
     ).toMatchObject(getPositionInCode(source, `bar`))
     expect(
-      consumer.originalPositionFor(getPositionInCode(code, `_ctx.bar`))
-    ).toMatchObject(getPositionInCode(source, `bar`))
+      consumer.originalPositionFor(getPositionInCode(code, `_ctx.bar`, `bar`))
+    ).toMatchObject(getPositionInCode(source, `bar`, true))
 
     expect(
-      consumer.originalPositionFor(getPositionInCode(code, `world`))
-    ).toMatchObject(getPositionInCode(source, `{{ world }}`))
+      consumer.originalPositionFor(getPositionInCode(code, `world`, true))
+    ).toMatchObject(getPositionInCode(source, `{{ world }}`, `world`))
     expect(
-      consumer.originalPositionFor(getPositionInCode(code, `_ctx.world`))
-    ).toMatchObject(getPositionInCode(source, `{{ world }}`))
+      consumer.originalPositionFor(
+        getPositionInCode(code, `_ctx.world`, `world`)
+      )
+    ).toMatchObject(getPositionInCode(source, `{{ world }}`, `world`))
 
     expect(
       consumer.originalPositionFor(getPositionInCode(code, `ok`))
     ).toMatchObject(getPositionInCode(source, `ok`))
     expect(
-      consumer.originalPositionFor(getPositionInCode(code, `_ctx.ok`))
-    ).toMatchObject(getPositionInCode(source, `ok`))
+      consumer.originalPositionFor(getPositionInCode(code, `_ctx.ok`, `ok`))
+    ).toMatchObject(getPositionInCode(source, `ok`, true))
 
     expect(
       consumer.originalPositionFor(getPositionInCode(code, `list`))
     ).toMatchObject(getPositionInCode(source, `list`))
     expect(
-      consumer.originalPositionFor(getPositionInCode(code, `_ctx.list`))
-    ).toMatchObject(getPositionInCode(source, `list`))
+      consumer.originalPositionFor(getPositionInCode(code, `_ctx.list`, `list`))
+    ).toMatchObject(getPositionInCode(source, `list`, true))
 
     expect(
       consumer.originalPositionFor(getPositionInCode(code, `value`))
@@ -188,29 +206,31 @@ describe('compiler: integration tests', () => {
       consumer.originalPositionFor(getPositionInCode(code, `bar`))
     ).toMatchObject(getPositionInCode(source, `bar`))
     expect(
-      consumer.originalPositionFor(getPositionInCode(code, `_ctx.bar`))
-    ).toMatchObject(getPositionInCode(source, `bar`))
+      consumer.originalPositionFor(getPositionInCode(code, `_ctx.bar`, `bar`))
+    ).toMatchObject(getPositionInCode(source, `bar`, true))
 
     expect(
-      consumer.originalPositionFor(getPositionInCode(code, `world`))
-    ).toMatchObject(getPositionInCode(source, `{{ world }}`))
+      consumer.originalPositionFor(getPositionInCode(code, `world`, true))
+    ).toMatchObject(getPositionInCode(source, `{{ world }}`, `world`))
     expect(
-      consumer.originalPositionFor(getPositionInCode(code, `_ctx.world`))
-    ).toMatchObject(getPositionInCode(source, `{{ world }}`))
+      consumer.originalPositionFor(
+        getPositionInCode(code, `_ctx.world`, `world`)
+      )
+    ).toMatchObject(getPositionInCode(source, `{{ world }}`, `world`))
 
     expect(
       consumer.originalPositionFor(getPositionInCode(code, `ok`))
     ).toMatchObject(getPositionInCode(source, `ok`))
     expect(
-      consumer.originalPositionFor(getPositionInCode(code, `_ctx.ok`))
-    ).toMatchObject(getPositionInCode(source, `ok`))
+      consumer.originalPositionFor(getPositionInCode(code, `_ctx.ok`, `ok`))
+    ).toMatchObject(getPositionInCode(source, `ok`, true))
 
     expect(
       consumer.originalPositionFor(getPositionInCode(code, `list`))
     ).toMatchObject(getPositionInCode(source, `list`))
     expect(
-      consumer.originalPositionFor(getPositionInCode(code, `_ctx.list`))
-    ).toMatchObject(getPositionInCode(source, `list`))
+      consumer.originalPositionFor(getPositionInCode(code, `_ctx.list`, `list`))
+    ).toMatchObject(getPositionInCode(source, `list`, true))
 
     expect(
       consumer.originalPositionFor(getPositionInCode(code, `value`))

+ 14 - 3
packages/compiler-core/src/codegen.ts

@@ -106,7 +106,19 @@ function createCodegenContext(
       context.code += code
       if (context.map) {
         if (node) {
-          const mapping = {
+          let name
+          if (
+            node.type === NodeTypes.EXPRESSION &&
+            !node.children &&
+            !node.isStatic
+          ) {
+            const content = node.content.replace(/^_ctx\./, '')
+            if (content !== node.content && isSimpleIdentifier(content)) {
+              name = content
+            }
+          }
+          context.map.addMapping({
+            name,
             source: context.filename,
             original: {
               line: node.loc.start.line,
@@ -116,8 +128,7 @@ function createCodegenContext(
               line: context.line,
               column: context.column - 1
             }
-          }
-          context.map.addMapping(mapping)
+          })
         }
         advancePositionWithMutation(context, code)
       }

+ 6 - 1
packages/compiler-core/src/transforms/transformStyle.ts

@@ -1,7 +1,12 @@
 import { NodeTransform } from '../transform'
 import { NodeTypes, createExpression } from '../ast'
 
-// prase inline CSS strings for static style attributes into an object
+// Parse inline CSS strings for static style attributes into an object.
+// This is a NodeTransform since it works on the static `style` attribute and
+// converts it into a dynamic equivalent:
+// style="color: red" -> :style='{ "color": "red" }'
+// It is then processed by `transformElement` and included in the generated
+// props.
 export const transformStyle: NodeTransform = (node, context) => {
   if (node.type === NodeTypes.ELEMENT) {
     node.props.forEach((p, i) => {