Kaynağa Gözat

wip: should not reuse AST when using custom compiler

Evan You 2 yıl önce
ebeveyn
işleme
79d3cc6cec

+ 27 - 0
packages/compiler-sfc/__tests__/compileTemplate.spec.ts

@@ -158,6 +158,33 @@ test('should work w/ AST from descriptor', () => {
   ).toMatchObject(getPositionInCode(source, `foobar`))
 })
 
+test('should not reuse AST if using custom compiler', () => {
+  const source = `
+  <template>
+    <div><p>{{ foobar }}</p></div>
+  </template>
+  `
+  const template = parse(source, {
+    filename: 'example.vue',
+    sourceMap: true
+  }).descriptor.template!
+
+  const { code } = compile({
+    filename: 'example.vue',
+    source: template.content,
+    ast: template.ast,
+    compiler: {
+      parse: () => null as any,
+      // @ts-ignore
+      compile: input => ({ code: input })
+    }
+  })
+
+  // what we really want to assert is that the `input` received by the custom
+  // compiler is the source string, not the AST.
+  expect(code).toBe(template.content)
+})
+
 test('template errors', () => {
   const result = compile({
     filename: 'example.vue',

+ 13 - 3
packages/compiler-sfc/src/compileTemplate.ts

@@ -173,7 +173,7 @@ function doCompileTemplate({
   ssr = false,
   ssrCssVars,
   isProd = false,
-  compiler = ssr ? (CompilerSSR as TemplateCompiler) : CompilerDOM,
+  compiler,
   compilerOptions = {},
   transformAssetUrls
 }: SFCTemplateCompileOptions): SFCTemplateCompileResults {
@@ -205,9 +205,19 @@ function doCompileTemplate({
   const shortId = id.replace(/^data-v-/, '')
   const longId = `data-v-${shortId}`
 
+  const defaultCompiler = ssr ? (CompilerSSR as TemplateCompiler) : CompilerDOM
+  compiler = compiler || defaultCompiler
+
+  if (compiler !== defaultCompiler) {
+    // user using custom compiler, this means we cannot reuse the AST from
+    // the descriptor as they might be different.
+    inAST = undefined
+  }
+
   if (inAST?.codegenNode) {
     // input AST has codegenNode - it has already been transformed and cannot
-    // be reused. We need to parse a fresh one.
+    // be reused. We need to parse a fresh one. Can't just use `source` here
+    // since we need the AST location info to be relative to the entire SFC.
     const newAST = compiler.parse(inAST.source, {
       parseMode: 'sfc',
       onError: e => errors.push(e)
@@ -241,7 +251,7 @@ function doCompileTemplate({
   // inMap should be the map produced by ./parse.ts which is a simple line-only
   // mapping. If it is present, we need to adjust the final map and errors to
   // reflect the original line numbers.
-  if (inMap) {
+  if (inMap && !inAST) {
     if (map) {
       map = mapLines(inMap, map)
     }

+ 1 - 4
packages/compiler-sfc/src/parse.ts

@@ -248,10 +248,7 @@ export function parse(
         )
       }
     }
-    // only genMap for template when it needs preprocessor
-    if (descriptor.template && descriptor.template.lang) {
-      genMap(descriptor.template)
-    }
+    genMap(descriptor.template)
     genMap(descriptor.script)
     descriptor.styles.forEach(genMap)
     descriptor.customBlocks.forEach(genMap)