mirror of https://github.com/vuejs/core.git
wip(compiler-vapor): support expressions in idMap
This commit is contained in:
parent
1ff6b136db
commit
5d88c53cd3
|
@ -1,6 +1,7 @@
|
||||||
import type {
|
import type {
|
||||||
CodegenOptions as BaseCodegenOptions,
|
CodegenOptions as BaseCodegenOptions,
|
||||||
BaseCodegenResult,
|
BaseCodegenResult,
|
||||||
|
SimpleExpressionNode,
|
||||||
} from '@vue/compiler-dom'
|
} from '@vue/compiler-dom'
|
||||||
import type { BlockIRNode, CoreHelper, RootIRNode, VaporHelper } from './ir'
|
import type { BlockIRNode, CoreHelper, RootIRNode, VaporHelper } from './ir'
|
||||||
import { extend, remove } from '@vue/shared'
|
import { extend, remove } from '@vue/shared'
|
||||||
|
@ -32,12 +33,16 @@ export class CodegenContext {
|
||||||
|
|
||||||
delegates: Set<string> = new Set<string>()
|
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)
|
seenInlineHandlerNames: Record<string, number> = Object.create(null)
|
||||||
|
|
||||||
block: BlockIRNode
|
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 { identifiers } = this
|
||||||
const ids = Object.keys(map)
|
const ids = Object.keys(map)
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,10 @@
|
||||||
import { NOOP, extend, genPropsAccessExp, isGloballyAllowed } from '@vue/shared'
|
import {
|
||||||
|
NOOP,
|
||||||
|
extend,
|
||||||
|
genPropsAccessExp,
|
||||||
|
isGloballyAllowed,
|
||||||
|
isString,
|
||||||
|
} from '@vue/shared'
|
||||||
import {
|
import {
|
||||||
BindingTypes,
|
BindingTypes,
|
||||||
NewlineType,
|
NewlineType,
|
||||||
|
@ -110,19 +116,26 @@ export function genExpression(
|
||||||
|
|
||||||
function genIdentifier(
|
function genIdentifier(
|
||||||
raw: string,
|
raw: string,
|
||||||
{ options, helper, identifiers }: CodegenContext,
|
context: CodegenContext,
|
||||||
loc?: SourceLocation,
|
loc?: SourceLocation,
|
||||||
assignment?: string,
|
assignment?: string,
|
||||||
id?: Identifier,
|
id?: Identifier,
|
||||||
parent?: Node,
|
parent?: Node,
|
||||||
parentStack?: Node[],
|
parentStack?: Node[],
|
||||||
): CodeFragment[] {
|
): CodeFragment[] {
|
||||||
|
const { options, helper, identifiers } = context
|
||||||
const { inline, bindingMetadata } = options
|
const { inline, bindingMetadata } = options
|
||||||
let name: string | undefined = raw
|
let name: string | undefined = raw
|
||||||
|
|
||||||
const idMap = identifiers[raw]
|
const idMap = identifiers[raw]
|
||||||
if (idMap && idMap.length) {
|
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
|
let prefix: string | undefined
|
||||||
|
|
|
@ -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 { genBlock } from './block'
|
||||||
import { genExpression } from './expression'
|
import { genExpression } from './expression'
|
||||||
import type { CodegenContext } from '../generate'
|
import type { CodegenContext } from '../generate'
|
||||||
import type { ForIRNode } from '../ir'
|
import type { ForIRNode } from '../ir'
|
||||||
import { type CodeFragment, NEWLINE, genCall, genMulti } from './utils'
|
import { type CodeFragment, NEWLINE, genCall, genMulti } from './utils'
|
||||||
import type { Identifier } from '@babel/types'
|
import type { Identifier } from '@babel/types'
|
||||||
|
import { parseExpression } from '@babel/parser'
|
||||||
|
|
||||||
export function genFor(
|
export function genFor(
|
||||||
oper: ForIRNode,
|
oper: ForIRNode,
|
||||||
|
@ -23,10 +28,19 @@ export function genFor(
|
||||||
|
|
||||||
const [depth, exitScope] = context.enterScope()
|
const [depth, exitScope] = context.enterScope()
|
||||||
const propsName = `_ctx${depth}`
|
const propsName = `_ctx${depth}`
|
||||||
const idMap: Record<string, string | null> = {}
|
const idMap: Record<string, string | SimpleExpressionNode | null> = {}
|
||||||
|
|
||||||
idToPathMap.forEach((path, id) => {
|
idToPathMap.forEach((pathInfo, id) => {
|
||||||
idMap[id] = `${propsName}[0].value${path}`
|
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 (rawKey) idMap[rawKey] = `${propsName}[1].value`
|
||||||
if (rawIndex) idMap[rawIndex] = `${propsName}[2].value`
|
if (rawIndex) idMap[rawIndex] = `${propsName}[2].value`
|
||||||
|
@ -54,7 +68,7 @@ export function genFor(
|
||||||
// construct a id -> accessor path map.
|
// construct a id -> accessor path map.
|
||||||
// e.g. `{ x: { y: [z] }}` -> `Map{ 'z' => '.x.y[0]' }`
|
// e.g. `{ x: { y: [z] }}` -> `Map{ 'z' => '.x.y[0]' }`
|
||||||
function parseValueDestructure() {
|
function parseValueDestructure() {
|
||||||
const map = new Map<string, string>()
|
const map = new Map<string, { path: string; dynamic: boolean } | null>()
|
||||||
if (value) {
|
if (value) {
|
||||||
rawValue = value && value.content
|
rawValue = value && value.content
|
||||||
if (value.ast) {
|
if (value.ast) {
|
||||||
|
@ -63,6 +77,7 @@ export function genFor(
|
||||||
(id, _, parentStack, ___, isLocal) => {
|
(id, _, parentStack, ___, isLocal) => {
|
||||||
if (isLocal) {
|
if (isLocal) {
|
||||||
let path = ''
|
let path = ''
|
||||||
|
let isDynamic = false
|
||||||
for (let i = 0; i < parentStack.length; i++) {
|
for (let i = 0; i < parentStack.length; i++) {
|
||||||
const parent = parentStack[i]
|
const parent = parentStack[i]
|
||||||
const child = parentStack[i + 1] || id
|
const child = parentStack[i + 1] || id
|
||||||
|
@ -71,10 +86,10 @@ export function genFor(
|
||||||
parent.value === child
|
parent.value === child
|
||||||
) {
|
) {
|
||||||
if (parent.computed && parent.key.type !== 'StringLiteral') {
|
if (parent.computed && parent.key.type !== 'StringLiteral') {
|
||||||
// TODO need to process this
|
isDynamic = true
|
||||||
path += `[${value.content.slice(
|
path += `[${value.content.slice(
|
||||||
parent.key.start!,
|
parent.key.start! - 1,
|
||||||
parent.key.end!,
|
parent.key.end! - 1,
|
||||||
)}]`
|
)}]`
|
||||||
} else if (parent.key.type === 'StringLiteral') {
|
} else if (parent.key.type === 'StringLiteral') {
|
||||||
path += `[${JSON.stringify(parent.key.value)}]`
|
path += `[${JSON.stringify(parent.key.value)}]`
|
||||||
|
@ -88,13 +103,13 @@ export function genFor(
|
||||||
}
|
}
|
||||||
// TODO handle rest spread
|
// TODO handle rest spread
|
||||||
}
|
}
|
||||||
map.set(id.name, path)
|
map.set(id.name, { path, dynamic: isDynamic })
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
true,
|
true,
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
map.set(rawValue, '')
|
map.set(rawValue, null)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return map
|
return map
|
||||||
|
|
Loading…
Reference in New Issue