Explorar o código

refactor(compiler-vapor): simplify generate code fragment

三咲智子 Kevin Deng hai 1 ano
pai
achega
72589be6aa

+ 13 - 34
packages/compiler-vapor/src/generate.ts

@@ -1,10 +1,8 @@
 import type {
   CodegenOptions as BaseCodegenOptions,
   BaseCodegenResult,
-  CodegenSourceMapGenerator,
 } from '@vue/compiler-dom'
 import type { BlockIRNode, IREffect, RootIRNode, VaporHelper } from './ir'
-import { SourceMapGenerator } from 'source-map-js'
 import { extend, remove } from '@vue/shared'
 import { genBlockContent } from './generators/block'
 import { genTemplates } from './generators/template'
@@ -24,10 +22,6 @@ export type CodegenOptions = Omit<BaseCodegenOptions, 'optimizeImports'>
 export class CodegenContext {
   options: Required<CodegenOptions>
 
-  code: CodeFragment[]
-  map?: CodegenSourceMapGenerator
-  push: (...args: CodeFragment[]) => void
-
   helpers = new Set<string>([])
   vaporHelpers = new Set<string>([])
   helper = (name: string) => {
@@ -92,21 +86,6 @@ export class CodegenContext {
     }
     this.options = extend(defaultOptions, options)
     this.block = ir.block
-
-    const [code, push] = buildCodeFragment()
-    this.code = code
-    this.push = push
-
-    const {
-      options: { filename, sourceMap },
-    } = this
-    if (!__BROWSER__ && sourceMap) {
-      // lazy require source-map implementation, only in non-browser builds
-      this.map =
-        new SourceMapGenerator() as unknown as CodegenSourceMapGenerator
-      this.map.setSourceContent(filename, ir.source)
-      this.map._sources.add(filename)
-    }
   }
 }
 
@@ -121,12 +100,13 @@ export function generate(
   ir: RootIRNode,
   options: CodegenOptions = {},
 ): VaporCodegenResult {
+  const [frag, push] = buildCodeFragment()
   const context = new CodegenContext(ir, options)
-  const { push, helpers, vaporHelpers } = context
-
+  const { helpers, vaporHelpers } = context
+  const { inline } = options
   const functionName = 'render'
-  const isSetupInlined = options.inline
-  if (isSetupInlined) {
+
+  if (inline) {
     push(`(() => {`)
   } else {
     push(NEWLINE, `export function ${functionName}(_ctx) {`)
@@ -136,33 +116,32 @@ export function generate(
   push(...genBlockContent(ir.block, context, true))
   push(INDENT_END, NEWLINE)
 
-  if (isSetupInlined) {
+  if (inline) {
     push('})()')
   } else {
     push('}')
   }
 
   const deligates = genDeligates(context)
-  // TODO source map?
   const templates = genTemplates(ir.template, context)
   const imports = genHelperImports(context)
   const preamble = imports + templates + deligates
 
   const newlineCount = [...preamble].filter(c => c === '\n').length
-  if (newlineCount && !isSetupInlined) {
-    context.code.unshift(...new Array<CodeFragment>(newlineCount).fill(LF))
+  if (newlineCount && !inline) {
+    frag.unshift(...new Array<CodeFragment>(newlineCount).fill(LF))
   }
 
-  let codegen = genCodeFragment(context)
-  if (!isSetupInlined) {
-    codegen = preamble + codegen
+  let [code, map] = genCodeFragment(frag, context)
+  if (!inline) {
+    code = preamble + code
   }
 
   return {
-    code: codegen,
+    code,
     ast: ir,
     preamble,
-    map: context.map ? context.map.toJSON() : undefined,
+    map: map && map.toJSON(),
     helpers,
     vaporHelpers,
   }

+ 23 - 6
packages/compiler-vapor/src/generators/utils.ts

@@ -1,4 +1,6 @@
+import { SourceMapGenerator } from 'source-map-js'
 import {
+  type CodegenSourceMapGenerator,
   NewlineType,
   type Position,
   type SourceLocation,
@@ -76,12 +78,27 @@ export function genCall(
   return [name, ...genMulti(['(', ')', ', '], ...frags)]
 }
 
-export function genCodeFragment(context: CodegenContext) {
+export function genCodeFragment(
+  code: CodeFragment[],
+  context: CodegenContext,
+): [code: string, map: CodegenSourceMapGenerator | undefined] {
+  const {
+    options: { filename, sourceMap },
+  } = context
+
+  let map: CodegenSourceMapGenerator | undefined
+  if (!__BROWSER__ && sourceMap) {
+    // lazy require source-map implementation, only in non-browser builds
+    map = new SourceMapGenerator() as unknown as CodegenSourceMapGenerator
+    map.setSourceContent(filename, context.ir.source)
+    map._sources.add(filename)
+  }
+
   let codegen = ''
   const pos = { line: 1, column: 1, offset: 0 }
   let indentLevel = 0
 
-  for (let frag of context.code) {
+  for (let frag of code) {
     if (!frag) continue
 
     if (frag === NEWLINE) {
@@ -104,7 +121,7 @@ export function genCodeFragment(context: CodegenContext) {
     let [code, newlineIndex = NewlineType.None, loc, name] = frag
     codegen += code
 
-    if (!__BROWSER__ && context.map) {
+    if (!__BROWSER__ && map) {
       if (loc) addMapping(loc.start, name)
       if (newlineIndex === NewlineType.Unknown) {
         // multiple newlines, full iteration
@@ -147,20 +164,20 @@ export function genCodeFragment(context: CodegenContext) {
     }
   }
 
-  return codegen
+  return [codegen, map]
 
   function addMapping(loc: Position, name: string | null = null) {
     // we use the private property to directly add the mapping
     // because the addMapping() implementation in source-map-js has a bunch of
     // unnecessary arg and validation checks that are pure overhead in our case.
-    const { _names, _mappings } = context.map!
+    const { _names, _mappings } = map!
     if (name !== null && !_names.has(name)) _names.add(name)
     _mappings.add({
       originalLine: loc.line,
       originalColumn: loc.column - 1, // source-map column is 0 based
       generatedLine: pos.line,
       generatedColumn: pos.column - 1,
-      source: context.options.filename,
+      source: filename,
       name,
     })
   }