wip(compiler-vapor): support expressions in idMap

This commit is contained in:
Evan You 2025-01-30 20:45:44 +08:00
parent 1ff6b136db
commit 5d88c53cd3
No known key found for this signature in database
GPG Key ID: 00E9AB7A6704CE0A
3 changed files with 48 additions and 15 deletions

View File

@ -1,6 +1,7 @@
import type {
CodegenOptions as BaseCodegenOptions,
BaseCodegenResult,
SimpleExpressionNode,
} from '@vue/compiler-dom'
import type { BlockIRNode, CoreHelper, RootIRNode, VaporHelper } from './ir'
import { extend, remove } from '@vue/shared'
@ -32,12 +33,16 @@ export class CodegenContext {
delegates: Set<string> = new Set<string>()
identifiers: Record<string, string[]> = Object.create(null)
identifiers: Record<string, (string | SimpleExpressionNode)[]> =
Object.create(null)
seenInlineHandlerNames: Record<string, number> = Object.create(null)
block: BlockIRNode
withId<T>(fn: () => T, map: Record<string, string | null>): T {
withId<T>(
fn: () => T,
map: Record<string, string | SimpleExpressionNode | null>,
): T {
const { identifiers } = this
const ids = Object.keys(map)

View File

@ -1,4 +1,10 @@
import { NOOP, extend, genPropsAccessExp, isGloballyAllowed } from '@vue/shared'
import {
NOOP,
extend,
genPropsAccessExp,
isGloballyAllowed,
isString,
} from '@vue/shared'
import {
BindingTypes,
NewlineType,
@ -110,19 +116,26 @@ export function genExpression(
function genIdentifier(
raw: string,
{ options, helper, identifiers }: CodegenContext,
context: CodegenContext,
loc?: SourceLocation,
assignment?: string,
id?: Identifier,
parent?: Node,
parentStack?: Node[],
): CodeFragment[] {
const { options, helper, identifiers } = context
const { inline, bindingMetadata } = options
let name: string | undefined = raw
const idMap = identifiers[raw]
if (idMap && idMap.length) {
return [[idMap[0], NewlineType.None, loc]]
const replacement = idMap[0]
if (isString(replacement)) {
return [[replacement, NewlineType.None, loc]]
} else {
// replacement is an expression - process it again
return genExpression(replacement, context, assignment)
}
}
let prefix: string | undefined

View File

@ -1,10 +1,15 @@
import { type SimpleExpressionNode, walkIdentifiers } from '@vue/compiler-dom'
import {
type SimpleExpressionNode,
createSimpleExpression,
walkIdentifiers,
} from '@vue/compiler-dom'
import { genBlock } from './block'
import { genExpression } from './expression'
import type { CodegenContext } from '../generate'
import type { ForIRNode } from '../ir'
import { type CodeFragment, NEWLINE, genCall, genMulti } from './utils'
import type { Identifier } from '@babel/types'
import { parseExpression } from '@babel/parser'
export function genFor(
oper: ForIRNode,
@ -23,10 +28,19 @@ export function genFor(
const [depth, exitScope] = context.enterScope()
const propsName = `_ctx${depth}`
const idMap: Record<string, string | null> = {}
const idMap: Record<string, string | SimpleExpressionNode | null> = {}
idToPathMap.forEach((path, id) => {
idMap[id] = `${propsName}[0].value${path}`
idToPathMap.forEach((pathInfo, id) => {
const path = `${propsName}[0].value${pathInfo ? pathInfo.path : ''}`
if (pathInfo && pathInfo.dynamic) {
const node = (idMap[id] = createSimpleExpression(path))
const plugins = context.options.expressionPlugins
node.ast = parseExpression(`(${path})`, {
plugins: plugins ? [...plugins, 'typescript'] : ['typescript'],
})
} else {
idMap[id] = path
}
})
if (rawKey) idMap[rawKey] = `${propsName}[1].value`
if (rawIndex) idMap[rawIndex] = `${propsName}[2].value`
@ -54,7 +68,7 @@ export function genFor(
// construct a id -> accessor path map.
// e.g. `{ x: { y: [z] }}` -> `Map{ 'z' => '.x.y[0]' }`
function parseValueDestructure() {
const map = new Map<string, string>()
const map = new Map<string, { path: string; dynamic: boolean } | null>()
if (value) {
rawValue = value && value.content
if (value.ast) {
@ -63,6 +77,7 @@ export function genFor(
(id, _, parentStack, ___, isLocal) => {
if (isLocal) {
let path = ''
let isDynamic = false
for (let i = 0; i < parentStack.length; i++) {
const parent = parentStack[i]
const child = parentStack[i + 1] || id
@ -71,10 +86,10 @@ export function genFor(
parent.value === child
) {
if (parent.computed && parent.key.type !== 'StringLiteral') {
// TODO need to process this
isDynamic = true
path += `[${value.content.slice(
parent.key.start!,
parent.key.end!,
parent.key.start! - 1,
parent.key.end! - 1,
)}]`
} else if (parent.key.type === 'StringLiteral') {
path += `[${JSON.stringify(parent.key.value)}]`
@ -88,13 +103,13 @@ export function genFor(
}
// TODO handle rest spread
}
map.set(id.name, path)
map.set(id.name, { path, dynamic: isDynamic })
}
},
true,
)
} else {
map.set(rawValue, '')
map.set(rawValue, null)
}
}
return map