]> git.ipfire.org Git - thirdparty/vuejs/core.git/commitdiff
refactor: helpers, import type, cleanup
author三咲智子 Kevin Deng <sxzz@sxzz.moe>
Fri, 24 Nov 2023 03:07:31 +0000 (11:07 +0800)
committer三咲智子 Kevin Deng <sxzz@sxzz.moe>
Fri, 24 Nov 2023 03:07:31 +0000 (11:07 +0800)
packages/compiler-vapor/__tests__/__snapshots__/basic.test.ts.snap
packages/compiler-vapor/src/compile.ts
packages/compiler-vapor/src/generate.ts
packages/compiler-vapor/src/index.ts
packages/compiler-vapor/src/ir.ts [new file with mode: 0644]
packages/compiler-vapor/src/transform.ts

index c00e8dbc719579c477eca2d1eea8c367e409919d..efb1dbb7b3860d957a34f3aa1377a91a28e34ae9 100644 (file)
@@ -3,7 +3,7 @@
 exports[`basic 1`] = `
 "import { defineComponent as _defineComponent } from 'vue'
 import { watchEffect } from 'vue'
-import { template, setAttr, setText, children, on, insert } from 'vue/vapor'
+import { template, insert, setText, on } from 'vue/vapor'
 const t0 = template(\`<h1 id=\\"title\\">Counter</h1><p>Count: </p><p>Double: </p><button>Increment</button>\`)
 import { ref, computed } from 'vue'
 
index 3c50396d4bebded677af62b15b6ee1701823c967..d31dad374e3f9f4cfc17d4e4f874fde4d02c365e 100644 (file)
@@ -1,7 +1,7 @@
 import {
-  CodegenResult,
-  CompilerOptions,
-  RootNode,
+  type CodegenResult,
+  type CompilerOptions,
+  type RootNode,
   baseParse,
 } from '@vue/compiler-dom'
 import { isString } from '@vue/shared'
index d809d093ce8beda8823496f827d479d8cbb9154f..8169678aced86d25b05671b893c575c50c44755b 100644 (file)
@@ -1,9 +1,9 @@
-import {
+import type {
   CodegenContext,
   CodegenOptions,
   CodegenResult,
 } from '@vue/compiler-dom'
-import { DynamicChildren, IRNodeTypes, RootIRNode } from './transform'
+import { type DynamicChildren, type RootIRNode, IRNodeTypes } from './ir'
 
 // IR -> JS codegen
 export function generate(
@@ -13,26 +13,28 @@ export function generate(
   } = {},
 ): CodegenResult {
   let code = ''
-  let preamble = `import { watchEffect } from 'vue'
-import { template, setAttr, setText, children, on, insert } from 'vue/vapor'\n`
+  let preamble = ''
 
-  const isSetupInlined = !!options.inline
-
-  preamble += ir.template
-    .map((template, i) => `const t${i} = template(\`${template.template}\`)\n`)
-    .join('')
+  const { helpers, vaporHelpers } = ir
+  if (ir.template.length) {
+    preamble += ir.template
+      .map(
+        (template, i) => `const t${i} = template(\`${template.template}\`)\n`,
+      )
+      .join('')
+    vaporHelpers.add('template')
+  }
 
   code += `const root = t0()\n`
-
   if (ir.children[0]) {
-    code += `const {${genChildrens(
-      ir.children[0].children,
-    )}} = children(root)\n`
+    code += `const {${genChildren(ir.children[0].children)}} = children(root)\n`
+    vaporHelpers.add('children')
   }
 
   for (const opration of ir.opration) {
     switch (opration.type) {
       case IRNodeTypes.TEXT_NODE: {
+        // TODO handle by runtime: document.createTextNode
         code += `const n${opration.id} = document.createTextNode(${opration.content})\n`
         break
       }
@@ -46,6 +48,7 @@ import { template, setAttr, setText, children, on, insert } from 'vue/vapor'\n`
             anchor = `, 0 /* InsertPosition.FIRST */`
           }
           code += `insert(n${opration.element}, n${opration.parent}${anchor})\n`
+          vaporHelpers.add('insert')
         }
         break
     }
@@ -53,21 +56,28 @@ import { template, setAttr, setText, children, on, insert } from 'vue/vapor'\n`
 
   for (const [expr, effects] of Object.entries(ir.effect)) {
     let scope = `watchEffect(() => {\n`
+    helpers.add('watchEffect')
     for (const effect of effects) {
       switch (effect.type) {
-        case IRNodeTypes.SET_PROP:
+        case IRNodeTypes.SET_PROP: {
           scope += `setAttr(n${effect.element}, ${JSON.stringify(
             effect.name,
           )}, undefined, ${expr})\n`
+          vaporHelpers.add('setAttr')
           break
-        case IRNodeTypes.SET_TEXT:
+        }
+        case IRNodeTypes.SET_TEXT: {
           scope += `setText(n${effect.element}, undefined, ${expr})\n`
+          vaporHelpers.add('setText')
           break
-        case IRNodeTypes.SET_EVENT:
+        }
+        case IRNodeTypes.SET_EVENT: {
           scope += `on(n${effect.element}, ${JSON.stringify(
             effect.name,
           )}, ${expr})\n`
+          vaporHelpers.add('on')
           break
+        }
       }
     }
     scope += '})\n'
@@ -76,7 +86,14 @@ import { template, setAttr, setText, children, on, insert } from 'vue/vapor'\n`
 
   code += 'return root'
 
+  if (vaporHelpers.size)
+    preamble =
+      `import { ${[...vaporHelpers].join(', ')} } from 'vue/vapor'\n` + preamble
+  if (helpers.size)
+    preamble = `import { ${[...helpers].join(', ')} } from 'vue'\n` + preamble
+
   const functionName = options.ssr ? `ssrRender` : `render`
+  const isSetupInlined = !!options.inline
   if (isSetupInlined) {
     code = `(() => {\n${code}\n})();`
   } else {
@@ -90,7 +107,7 @@ import { template, setAttr, setText, children, on, insert } from 'vue/vapor'\n`
   }
 }
 
-function genChildrens(children: DynamicChildren) {
+function genChildren(children: DynamicChildren) {
   let str = ''
   for (const [index, child] of Object.entries(children)) {
     str += ` ${index}: [`
@@ -98,7 +115,7 @@ function genChildrens(children: DynamicChildren) {
       str += `n${child.id}`
     }
     if (Object.keys(child.children).length) {
-      str += `, {${genChildrens(child.children)}}`
+      str += `, {${genChildren(child.children)}}`
     }
     str += '],'
   }
index dae557481ce60aea1e1a98da7461b18482628a1f..d64408d700bc2c49a85a81ad4a91e834babcc46a 100644 (file)
@@ -2,3 +2,4 @@ export { parse } from '@vue/compiler-dom'
 export { transform } from './transform'
 export { generate } from './generate'
 export { compile } from './compile'
+export * from './ir'
diff --git a/packages/compiler-vapor/src/ir.ts b/packages/compiler-vapor/src/ir.ts
new file mode 100644 (file)
index 0000000..c515797
--- /dev/null
@@ -0,0 +1,72 @@
+import type { SourceLocation } from '@vue/compiler-dom'
+
+export const enum IRNodeTypes {
+  ROOT,
+  TEMPLATE_GENERATOR,
+  SET_PROP,
+  SET_TEXT,
+  SET_EVENT,
+
+  INSERT_NODE,
+  TEXT_NODE,
+}
+
+export interface IRNode {
+  type: IRNodeTypes
+  loc: SourceLocation
+}
+
+export interface RootIRNode extends IRNode {
+  type: IRNodeTypes.ROOT
+  template: Array<TemplateGeneratorIRNode>
+  children: DynamicChildren
+  effect: Record<string, EffectNode[]>
+  opration: OprationNode[]
+  helpers: Set<string>
+  vaporHelpers: Set<string>
+}
+
+export interface TemplateGeneratorIRNode extends IRNode {
+  type: IRNodeTypes.TEMPLATE_GENERATOR
+  template: string
+}
+
+export interface SetPropIRNode extends IRNode {
+  type: IRNodeTypes.SET_PROP
+  element: number
+  name: string
+}
+
+export interface SetTextIRNode extends IRNode {
+  type: IRNodeTypes.SET_TEXT
+  element: number
+}
+
+export interface SetEventIRNode extends IRNode {
+  type: IRNodeTypes.SET_EVENT
+  element: number
+  name: string
+}
+
+export interface TextNodeIRNode extends IRNode {
+  type: IRNodeTypes.TEXT_NODE
+  id: number
+  content: string
+}
+
+export interface InsertNodeIRNode extends IRNode {
+  type: IRNodeTypes.INSERT_NODE
+  element: number
+  parent: number
+  anchor: number | 'first' | 'last'
+}
+
+export type EffectNode = SetPropIRNode | SetTextIRNode | SetEventIRNode
+export type OprationNode = TextNodeIRNode | InsertNodeIRNode
+
+export interface DynamicChild {
+  id: number | null
+  store: boolean
+  children: DynamicChildren
+}
+export type DynamicChildren = Record<number, DynamicChild>
index a8c5774570b6f36b1769c99c1694c064eead730c..270ee758830165c2f311332220e0950a9f819333 100644 (file)
@@ -1,85 +1,21 @@
-import {
-  type NodeTypes,
+import type {
+  NodeTypes,
   RootNode,
   Node,
   TemplateChildNode,
   ElementNode,
   AttributeNode,
-  SourceLocation,
   InterpolationNode,
   TransformOptions,
   DirectiveNode,
 } from '@vue/compiler-dom'
-
-export const enum IRNodeTypes {
-  ROOT,
-  TEMPLATE_GENERATOR,
-  SET_PROP,
-  SET_TEXT,
-  SET_EVENT,
-
-  INSERT_NODE,
-  TEXT_NODE,
-}
-
-export interface IRNode {
-  type: IRNodeTypes
-  loc: SourceLocation
-}
-
-export interface RootIRNode extends IRNode {
-  type: IRNodeTypes.ROOT
-  template: Array<TemplateGeneratorIRNode>
-  children: DynamicChildren
-  effect: Record<string, EffectNode[]>
-  opration: OprationNode[]
-  helpers: Set<string>
-}
-
-export interface TemplateGeneratorIRNode extends IRNode {
-  type: IRNodeTypes.TEMPLATE_GENERATOR
-  template: string
-}
-
-export interface SetPropIRNode extends IRNode {
-  type: IRNodeTypes.SET_PROP
-  element: number
-  name: string
-}
-
-export interface SetTextIRNode extends IRNode {
-  type: IRNodeTypes.SET_TEXT
-  element: number
-}
-
-export interface SetEventIRNode extends IRNode {
-  type: IRNodeTypes.SET_EVENT
-  element: number
-  name: string
-}
-
-export interface TextNodeIRNode extends IRNode {
-  type: IRNodeTypes.TEXT_NODE
-  id: number
-  content: string
-}
-
-export interface InsertNodeIRNode extends IRNode {
-  type: IRNodeTypes.INSERT_NODE
-  element: number
-  parent: number
-  anchor: number | 'first' | 'last'
-}
-
-export type EffectNode = SetPropIRNode | SetTextIRNode | SetEventIRNode
-export type OprationNode = TextNodeIRNode | InsertNodeIRNode
-
-export interface DynamicChild {
-  id: number | null
-  store: boolean
-  children: DynamicChildren
-}
-export type DynamicChildren = Record<number, DynamicChild>
+import {
+  type DynamicChildren,
+  type EffectNode,
+  type OprationNode,
+  type RootIRNode,
+  IRNodeTypes,
+} from './ir'
 
 export interface TransformContext<T extends Node = Node> {
   node: T
@@ -87,15 +23,17 @@ export interface TransformContext<T extends Node = Node> {
   root: TransformContext<RootNode>
   index: number
   options: TransformOptions
-  ir: RootIRNode
+  // ir: RootIRNode
   template: string
   children: DynamicChildren
   store: boolean
   ghost: boolean
 
   getElementId(): number
-  registerEffect(expr: string, effectNode: EffectNode): void
   registerTemplate(): number
+  registerEffect(expr: string, effectNode: EffectNode): void
+  registerOpration(...oprations: OprationNode[]): void
+  helper(name: string): string
 }
 
 function createRootContext(
@@ -104,7 +42,7 @@ function createRootContext(
   options: TransformOptions,
 ): TransformContext<RootNode> {
   let i = 0
-  const { effect: bindings } = ir
+  const { effect, opration, helpers, vaporHelpers } = ir
 
   const ctx: TransformContext<RootNode> = {
     node,
@@ -112,15 +50,14 @@ function createRootContext(
     index: 0,
     root: undefined as any, // set later
     options,
-    ir,
     children: {},
     store: false,
     ghost: false,
 
     getElementId: () => i++,
     registerEffect(expr, effectNode) {
-      if (!bindings[expr]) bindings[expr] = []
-      bindings[expr].push(effectNode)
+      if (!effect[expr]) effect[expr] = []
+      effect[expr].push(effectNode)
     },
 
     template: '',
@@ -137,6 +74,14 @@ function createRootContext(
       })
       return ir.template.length - 1
     },
+    registerOpration(...node) {
+      opration.push(...node)
+    },
+    // TODO not used yet
+    helper(name, vapor = true) {
+      ;(vapor ? vaporHelpers : helpers).add(name)
+      return name
+    },
   }
   ctx.root = ctx
   return ctx
@@ -178,12 +123,6 @@ export function transform(
   root: RootNode,
   options: TransformOptions = {},
 ): RootIRNode {
-  // {
-  //   type: IRNodeTypes.TEMPLATE_GENERATOR,
-  //   template,
-  //   loc: root.loc
-  // }
-
   const ir: RootIRNode = {
     type: IRNodeTypes.ROOT,
     loc: root.loc,
@@ -191,7 +130,8 @@ export function transform(
     children: {},
     effect: Object.create(null),
     opration: [],
-    helpers: new Set(['template']),
+    helpers: new Set([]),
+    vaporHelpers: new Set([]),
   }
   const ctx = createRootContext(ir, root, options)
   transformChildren(ctx, true)
@@ -303,7 +243,7 @@ function transformInterpolation(
         anchor = isFirst ? 'first' : 'last'
       }
 
-      ctx.ir.opration.push(
+      ctx.registerOpration(
         {
           type: IRNodeTypes.TEXT_NODE,
           loc: node.loc,
@@ -379,6 +319,7 @@ function transformProp(
   }
 }
 
+// TODO: reference packages/compiler-core/src/transforms/transformExpression.ts
 function processExpression(ctx: TransformContext, expr: string) {
   if (ctx.options.bindingMetadata?.[expr] === 'setup-ref') {
     expr += '.value'