Browse Source

refactor(compiler-vapor): remove ir expression

三咲智子 Kevin Deng 2 years ago
parent
commit
8fb01504da

+ 0 - 2
packages/compiler-vapor/__tests__/transforms/transformInterpolation.spec.ts

@@ -1,2 +0,0 @@
-// TODO: add tests for this transform
-test('baisc', () => {})

+ 4 - 0
packages/compiler-vapor/__tests__/transforms/transformRef.spec.ts

@@ -0,0 +1,4 @@
+// TODO: add tests for this transform
+describe('compiler: template ref transform', () => {
+  test.todo('basic')
+})

+ 4 - 0
packages/compiler-vapor/__tests__/transforms/transformText.spec.ts

@@ -0,0 +1,4 @@
+// TODO: add tests for this transform
+describe('compiler: text transform', () => {
+  test.todo('basic')
+})

+ 4 - 0
packages/compiler-vapor/__tests__/transforms/vModel.spec.ts

@@ -0,0 +1,4 @@
+// TODO: add tests for this transform
+describe('compiler: vModel transform', () => {
+  test.todo('basic')
+})

+ 3 - 4
packages/compiler-vapor/src/generators/expression.ts

@@ -1,15 +1,15 @@
 import {
   BindingTypes,
   NewlineType,
+  type SimpleExpressionNode,
   type SourceLocation,
   advancePositionWithClone,
   isInDestructureAssignment,
   isStaticProperty,
   walkIdentifiers,
 } from '@vue/compiler-dom'
-import { isGloballyAllowed, isString, makeMap } from '@vue/shared'
+import { isGloballyAllowed, makeMap } from '@vue/shared'
 import type { Identifier } from '@babel/types'
-import type { IRExpression } from '../ir'
 import {
   type CodeFragment,
   type CodegenContext,
@@ -18,13 +18,12 @@ import {
 import type { Node } from '@babel/types'
 
 export function genExpression(
-  node: IRExpression,
+  node: SimpleExpressionNode,
   context: CodegenContext,
 ): CodeFragment[] {
   const {
     options: { prefixIdentifiers },
   } = context
-  if (isString(node)) return [node]
 
   const { content: rawExpr, ast, isStatic, loc } = node
   if (isStatic) {

+ 3 - 3
packages/compiler-vapor/src/generators/modelValue.ts

@@ -1,4 +1,4 @@
-import { camelize, isString } from '@vue/shared'
+import { camelize } from '@vue/shared'
 import { genExpression } from './expression'
 import type { SetModelValueIRNode } from '../ir'
 import { type CodeFragment, type CodegenContext, NEWLINE } from '../generate'
@@ -13,8 +13,8 @@ export function genSetModelValue(
     options: { isTS },
   } = context
 
-  const name = isString(oper.key)
-    ? [JSON.stringify(`update:${camelize(oper.key)}`)]
+  const name = oper.key.isStatic
+    ? [JSON.stringify(`update:${camelize(oper.key.content)}`)]
     : ['`update:${', ...genExpression(oper.key, context), '}`']
   const handler = [
     (isTS ? `($event: any)` : `$event`) + ' => ((',

+ 8 - 9
packages/compiler-vapor/src/ir.ts

@@ -64,7 +64,7 @@ export interface RootIRNode extends Omit<BlockFunctionIRNode, 'type'> {
 export interface IfIRNode extends BaseIRNode {
   type: IRNodeTypes.IF
   id: number
-  condition: IRExpression
+  condition: SimpleExpressionNode
   positive: BlockFunctionIRNode
   negative?: BlockFunctionIRNode | IfIRNode
 }
@@ -72,7 +72,7 @@ export interface IfIRNode extends BaseIRNode {
 export interface ForIRNode extends BaseIRNode {
   type: IRNodeTypes.FOR
   id: number
-  source: IRExpression
+  source: SimpleExpressionNode
   value?: SimpleExpressionNode
   key?: SimpleExpressionNode
   index?: SimpleExpressionNode
@@ -111,7 +111,7 @@ export type KeyOverride = [find: string, replacement: string]
 export interface SetEventIRNode extends BaseIRNode {
   type: IRNodeTypes.SET_EVENT
   element: number
-  key: IRExpression
+  key: SimpleExpressionNode
   value?: SimpleExpressionNode
   modifiers: {
     // modifiers for addEventListener() options, e.g. .passive & .capture
@@ -127,20 +127,20 @@ export interface SetEventIRNode extends BaseIRNode {
 export interface SetHtmlIRNode extends BaseIRNode {
   type: IRNodeTypes.SET_HTML
   element: number
-  value: IRExpression
+  value: SimpleExpressionNode
 }
 
 export interface SetRefIRNode extends BaseIRNode {
   type: IRNodeTypes.SET_REF
   element: number
-  value: IRExpression
+  value: SimpleExpressionNode
 }
 
 export interface SetModelValueIRNode extends BaseIRNode {
   type: IRNodeTypes.SET_MODEL_VALUE
   element: number
-  key: IRExpression
-  value: IRExpression
+  key: SimpleExpressionNode
+  value: SimpleExpressionNode
   bindingType?: BindingTypes
   isComponent: boolean
 }
@@ -218,9 +218,8 @@ export interface IRDynamicInfo {
   children: IRDynamicInfo[]
 }
 
-export type IRExpression = SimpleExpressionNode | string
 export interface IREffect {
-  expressions: IRExpression[]
+  expressions: SimpleExpressionNode[]
   operations: OperationNode[]
 }
 

+ 13 - 18
packages/compiler-vapor/src/transform.ts

@@ -11,6 +11,7 @@ import {
   type SimpleExpressionNode,
   type TemplateChildNode,
   type TemplateNode,
+  createSimpleExpression,
   defaultOnError,
   defaultOnWarn,
   isVSlot,
@@ -21,7 +22,6 @@ import {
   DynamicFlag,
   type HackOptions,
   type IRDynamicInfo,
-  type IRExpression,
   IRNodeTypes,
   type OperationNode,
   type RootIRNode,
@@ -77,7 +77,7 @@ export interface TransformContext<T extends AllNode = AllNode> {
   increaseId(): number
   registerTemplate(): number
   registerEffect(
-    expressions: Array<IRExpression | null | undefined>,
+    expressions: SimpleExpressionNode[],
     operation: OperationNode[],
   ): void
   registerOperation(...operations: OperationNode[]): void
@@ -153,35 +153,28 @@ function createRootContext(
       return (this.dynamic.id = this.increaseId())
     },
     registerEffect(expressions, operations) {
-      if (
-        this.inVOnce ||
-        (expressions = expressions.filter(Boolean)).length === 0
-      ) {
+      expressions = expressions.filter(exp => !exp.isStatic)
+      if (this.inVOnce || expressions.length === 0) {
         return this.registerOperation(...operations)
       }
       const existing = this.block.effect.find(e =>
-        isSameExpression(e.expressions, expressions as IRExpression[]),
+        isSameExpression(e.expressions, expressions),
       )
       if (existing) {
         existing.operations.push(...operations)
       } else {
         this.block.effect.push({
-          expressions: expressions as IRExpression[],
+          expressions,
           operations,
         })
       }
 
-      function isSameExpression(a: IRExpression[], b: IRExpression[]) {
-        a = a.filter(filterStatic)
-        b = b.filter(filterStatic)
+      function isSameExpression(
+        a: SimpleExpressionNode[],
+        b: SimpleExpressionNode[],
+      ) {
         if (a.length !== b.length) return false
-        return (a as SimpleExpressionNode[]).every(
-          (exp, i) => exp.content === (b as SimpleExpressionNode[])[i].content,
-        )
-      }
-
-      function filterStatic(exp: IRExpression): exp is SimpleExpressionNode {
-        return !isString(exp) && !exp.isStatic
+        return a.every((exp, i) => exp.content === b[i].content)
       }
     },
 
@@ -434,3 +427,5 @@ export function wrapTemplate(node: ElementNode, dirs: string[]): TemplateNode {
     children: [extend({}, node, { props: pass } as TemplateChildNode)],
   } as Partial<TemplateNode>)
 }
+
+export const EMPTY_EXPRESSION = createSimpleExpression('', true)

+ 8 - 9
packages/compiler-vapor/src/transforms/transformElement.ts

@@ -14,10 +14,11 @@ import {
   isReservedProp,
   isVoidTag,
 } from '@vue/shared'
-import type {
-  DirectiveTransformResult,
-  NodeTransform,
-  TransformContext,
+import {
+  type DirectiveTransformResult,
+  EMPTY_EXPRESSION,
+  type NodeTransform,
+  type TransformContext,
 } from '../transform'
 import {
   IRNodeTypes,
@@ -154,11 +155,9 @@ function transformProp(
   if (prop.type === NodeTypes.ATTRIBUTE) {
     return {
       key: createSimpleExpression(prop.name, true, prop.nameLoc),
-      value: createSimpleExpression(
-        prop.value ? prop.value.content : '',
-        true,
-        prop.value && prop.value.loc,
-      ),
+      value: prop.value
+        ? createSimpleExpression(prop.value.content, true, prop.value.loc)
+        : EMPTY_EXPRESSION,
     }
   }
 

+ 12 - 8
packages/compiler-vapor/src/transforms/transformRef.ts

@@ -1,25 +1,29 @@
 import {
+  type AttributeNode,
   NodeTypes,
   type SimpleExpressionNode,
+  createSimpleExpression,
   findProp,
 } from '@vue/compiler-dom'
-import type { NodeTransform } from '../transform'
-import { type IRExpression, IRNodeTypes } from '../ir'
+import { EMPTY_EXPRESSION, type NodeTransform } from '../transform'
+import { IRNodeTypes, type VaporDirectiveNode } from '../ir'
 import { normalizeBindShorthand } from './vBind'
 
 export const transformRef: NodeTransform = (node, context) => {
   if (node.type !== NodeTypes.ELEMENT) return
-  const dir = findProp(node, 'ref', false, true)
+  const dir = findProp(node, 'ref', false, true) as
+    | VaporDirectiveNode
+    | AttributeNode
 
   if (!dir) return
 
-  let value: IRExpression
+  let value: SimpleExpressionNode
   if (dir.type === NodeTypes.DIRECTIVE) {
-    value =
-      (dir.exp as SimpleExpressionNode | undefined) ||
-      normalizeBindShorthand(dir.arg as SimpleExpressionNode, context)
+    value = dir.exp || normalizeBindShorthand(dir.arg!, context)
   } else {
-    value = dir.value ? JSON.stringify(dir.value.content) : '""'
+    value = dir.value
+      ? createSimpleExpression(dir.value.content, true, dir.value.loc)
+      : EMPTY_EXPRESSION
   }
 
   context.registerOperation({

+ 4 - 3
packages/compiler-vapor/src/transforms/vHtml.ts

@@ -1,13 +1,14 @@
 import { IRNodeTypes } from '../ir'
-import type { DirectiveTransform } from '../transform'
+import { type DirectiveTransform, EMPTY_EXPRESSION } from '../transform'
 import { DOMErrorCodes, createDOMCompilerError } from '@vue/compiler-dom'
 
 export const transformVHtml: DirectiveTransform = (dir, node, context) => {
-  const { exp, loc } = dir
+  let { exp, loc } = dir
   if (!exp) {
     context.options.onError(
       createDOMCompilerError(DOMErrorCodes.X_V_HTML_NO_EXPRESSION, loc),
     )
+    exp = EMPTY_EXPRESSION
   }
   if (node.children.length) {
     context.options.onError(
@@ -22,7 +23,7 @@ export const transformVHtml: DirectiveTransform = (dir, node, context) => {
       {
         type: IRNodeTypes.SET_HTML,
         element: context.reference(),
-        value: exp || '""',
+        value: exp,
       },
     ],
   )

+ 2 - 1
packages/compiler-vapor/src/transforms/vModel.ts

@@ -6,6 +6,7 @@ import {
   NodeTypes,
   createCompilerError,
   createDOMCompilerError,
+  createSimpleExpression,
   findDir,
   findProp,
   hasDynamicKeyVBind,
@@ -137,7 +138,7 @@ export const transformVModel: DirectiveTransform = (dir, node, context) => {
   context.registerOperation({
     type: IRNodeTypes.SET_MODEL_VALUE,
     element: context.reference(),
-    key: (arg && arg.isStatic ? arg.content : arg) || 'modelValue',
+    key: arg || createSimpleExpression('modelValue', true),
     value: exp,
     isComponent,
   })

+ 5 - 8
packages/compiler-vapor/src/transforms/vText.ts

@@ -1,17 +1,14 @@
-import {
-  DOMErrorCodes,
-  createDOMCompilerError,
-  createSimpleExpression,
-} from '@vue/compiler-dom'
-import type { DirectiveTransform } from '../transform'
+import { DOMErrorCodes, createDOMCompilerError } from '@vue/compiler-dom'
+import { type DirectiveTransform, EMPTY_EXPRESSION } from '../transform'
 import { IRNodeTypes } from '../ir'
 
 export const transformVText: DirectiveTransform = (dir, node, context) => {
-  const { exp, loc } = dir
+  let { exp, loc } = dir
   if (!exp) {
     context.options.onError(
       createDOMCompilerError(DOMErrorCodes.X_V_TEXT_NO_EXPRESSION, loc),
     )
+    exp = EMPTY_EXPRESSION
   }
   if (node.children.length) {
     context.options.onError(
@@ -26,7 +23,7 @@ export const transformVText: DirectiveTransform = (dir, node, context) => {
       {
         type: IRNodeTypes.SET_TEXT,
         element: context.reference(),
-        values: [exp || createSimpleExpression('', true)],
+        values: [exp],
       },
     ],
   )