From 79d3cc6cec8379162b1a6fdc2817f70dc141d416 Mon Sep 17 00:00:00 2001 From: Evan You Date: Wed, 22 Nov 2023 17:00:39 +0800 Subject: [PATCH] wip: should not reuse AST when using custom compiler --- .../__tests__/compileTemplate.spec.ts | 27 +++++++++++++++++++ packages/compiler-sfc/src/compileTemplate.ts | 16 ++++++++--- packages/compiler-sfc/src/parse.ts | 5 +--- 3 files changed, 41 insertions(+), 7 deletions(-) diff --git a/packages/compiler-sfc/__tests__/compileTemplate.spec.ts b/packages/compiler-sfc/__tests__/compileTemplate.spec.ts index ca298df475e..3b74dd66ada 100644 --- a/packages/compiler-sfc/__tests__/compileTemplate.spec.ts +++ b/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 = ` + + ` + 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', diff --git a/packages/compiler-sfc/src/compileTemplate.ts b/packages/compiler-sfc/src/compileTemplate.ts index 30d30072bfe..c34342a7a0c 100644 --- a/packages/compiler-sfc/src/compileTemplate.ts +++ b/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) } diff --git a/packages/compiler-sfc/src/parse.ts b/packages/compiler-sfc/src/parse.ts index 618ffca2e66..a84a0816006 100644 --- a/packages/compiler-sfc/src/parse.ts +++ b/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)