]> git.ipfire.org Git - thirdparty/vuejs/core.git/commitdiff
wip: should not reuse AST when using custom compiler
authorEvan You <yyx990803@gmail.com>
Wed, 22 Nov 2023 09:00:39 +0000 (17:00 +0800)
committerEvan You <yyx990803@gmail.com>
Sat, 25 Nov 2023 08:18:29 +0000 (16:18 +0800)
packages/compiler-sfc/__tests__/compileTemplate.spec.ts
packages/compiler-sfc/src/compileTemplate.ts
packages/compiler-sfc/src/parse.ts

index ca298df475e4da562785b4d0e17f34b39030c817..3b74dd66ada11762d2fa44ba32948f2a4cd7bf37 100644 (file)
@@ -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',
index 30d30072bfe2a6d4736794d0962c87fd565ff011..c34342a7a0c1557ab023891e7b0c5b2b4c940067 100644 (file)
@@ -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)
     }
index 618ffca2e667760da9640d92344046441c5cd886..a84a0816006842b586e5a106b86e0c7d031104ee 100644 (file)
@@ -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)