|
|
@@ -1,4 +1,4 @@
|
|
|
-import { walkIdentifiers } from '@vue/compiler-dom'
|
|
|
+import { type SimpleExpressionNode, walkIdentifiers } from '@vue/compiler-dom'
|
|
|
import { genBlock } from './block'
|
|
|
import { genExpression } from './expression'
|
|
|
import type { CodegenContext } from '../generate'
|
|
|
@@ -16,7 +16,7 @@ export function genFor(
|
|
|
context: CodegenContext,
|
|
|
): CodeFragment[] {
|
|
|
const { vaporHelper } = context
|
|
|
- const { source, value, key, index, render, keyProp, once, id } = oper
|
|
|
+ const { source, value, key, index, render, keyProp, once, id, memo } = oper
|
|
|
|
|
|
let isDestructureAssignment = false
|
|
|
let rawValue: string | null = null
|
|
|
@@ -24,67 +24,13 @@ export function genFor(
|
|
|
const rawIndex = index && index.content
|
|
|
|
|
|
const sourceExpr = ['() => (', ...genExpression(source, context), ')']
|
|
|
-
|
|
|
- const idsOfValue = new Set<string>()
|
|
|
- if (value) {
|
|
|
- rawValue = value && value.content
|
|
|
- if ((isDestructureAssignment = !!value.ast)) {
|
|
|
- walkIdentifiers(
|
|
|
- value.ast,
|
|
|
- (id, _, __, ___, isLocal) => {
|
|
|
- if (isLocal) idsOfValue.add(id.name)
|
|
|
- },
|
|
|
- true,
|
|
|
- )
|
|
|
- } else {
|
|
|
- idsOfValue.add(rawValue)
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- const [depth, exitScope] = context.enterScope()
|
|
|
- let propsName: string
|
|
|
- const idMap: Record<string, string | null> = {}
|
|
|
- if (context.options.prefixIdentifiers) {
|
|
|
- propsName = `_ctx${depth}`
|
|
|
- Array.from(idsOfValue).forEach(
|
|
|
- (id, idIndex) => (idMap[id] = `${propsName}[${idIndex}].value`),
|
|
|
- )
|
|
|
- if (rawKey) idMap[rawKey] = `${propsName}[${idsOfValue.size}].value`
|
|
|
- if (rawIndex) idMap[rawIndex] = `${propsName}[${idsOfValue.size + 1}].value`
|
|
|
- } else {
|
|
|
- propsName = `[${[rawValue || ((rawKey || rawIndex) && '_'), rawKey || (rawIndex && '__'), rawIndex].filter(Boolean).join(', ')}]`
|
|
|
- }
|
|
|
-
|
|
|
- let blockFn = context.withId(
|
|
|
- () => genBlock(render, context, [propsName]),
|
|
|
- idMap,
|
|
|
- )
|
|
|
- exitScope()
|
|
|
-
|
|
|
- let getKeyFn: CodeFragment[] | false = false
|
|
|
- if (keyProp) {
|
|
|
- const idMap: Record<string, null> = {}
|
|
|
- if (rawKey) idMap[rawKey] = null
|
|
|
- if (rawIndex) idMap[rawIndex] = null
|
|
|
- idsOfValue.forEach(id => (idMap[id] = null))
|
|
|
-
|
|
|
- const expr = context.withId(() => genExpression(keyProp, context), idMap)
|
|
|
- getKeyFn = [
|
|
|
- ...genMulti(
|
|
|
- ['(', ')', ', '],
|
|
|
- rawValue ? rawValue : rawKey || rawIndex ? '_' : undefined,
|
|
|
- rawKey ? rawKey : rawIndex ? '__' : undefined,
|
|
|
- rawIndex,
|
|
|
- ),
|
|
|
- ' => (',
|
|
|
- ...expr,
|
|
|
- ')',
|
|
|
- ]
|
|
|
- }
|
|
|
+ const idsInValue = getIdsInValue()
|
|
|
+ let blockFn = genBlockFn()
|
|
|
+ const simpleIdMap: Record<string, null> = genSimpleIdMap()
|
|
|
|
|
|
if (isDestructureAssignment) {
|
|
|
const idMap: Record<string, null> = {}
|
|
|
- idsOfValue.forEach(id => (idMap[id] = null))
|
|
|
+ idsInValue.forEach(id => (idMap[id] = null))
|
|
|
if (rawKey) idMap[rawKey] = null
|
|
|
if (rawIndex) idMap[rawIndex] = null
|
|
|
const destructureAssignmentFn: CodeFragment[] = [
|
|
|
@@ -96,7 +42,7 @@ export function genFor(
|
|
|
rawIndex,
|
|
|
),
|
|
|
') => ',
|
|
|
- ...genMulti(DELIMITERS_ARRAY, ...idsOfValue, rawKey, rawIndex),
|
|
|
+ ...genMulti(DELIMITERS_ARRAY, ...idsInValue, rawKey, rawIndex),
|
|
|
]
|
|
|
|
|
|
blockFn = genCall(
|
|
|
@@ -113,10 +59,77 @@ export function genFor(
|
|
|
vaporHelper('createFor'),
|
|
|
sourceExpr,
|
|
|
blockFn,
|
|
|
- getKeyFn,
|
|
|
- false, // todo: getMemo
|
|
|
+ genCallback(keyProp),
|
|
|
+ genCallback(memo),
|
|
|
false, // todo: hydrationNode
|
|
|
once && 'true',
|
|
|
),
|
|
|
]
|
|
|
+
|
|
|
+ function getIdsInValue() {
|
|
|
+ const idsInValue = new Set<string>()
|
|
|
+ if (value) {
|
|
|
+ rawValue = value && value.content
|
|
|
+ if ((isDestructureAssignment = !!value.ast)) {
|
|
|
+ walkIdentifiers(
|
|
|
+ value.ast,
|
|
|
+ (id, _, __, ___, isLocal) => {
|
|
|
+ if (isLocal) idsInValue.add(id.name)
|
|
|
+ },
|
|
|
+ true,
|
|
|
+ )
|
|
|
+ } else {
|
|
|
+ idsInValue.add(rawValue)
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return idsInValue
|
|
|
+ }
|
|
|
+
|
|
|
+ function genBlockFn() {
|
|
|
+ const [depth, exitScope] = context.enterScope()
|
|
|
+ let propsName: string
|
|
|
+ const idMap: Record<string, string | null> = {}
|
|
|
+ if (context.options.prefixIdentifiers) {
|
|
|
+ propsName = `_ctx${depth}`
|
|
|
+ Array.from(idsInValue).forEach(
|
|
|
+ (id, idIndex) => (idMap[id] = `${propsName}[${idIndex}].value`),
|
|
|
+ )
|
|
|
+ if (rawKey) idMap[rawKey] = `${propsName}[${idsInValue.size}].value`
|
|
|
+ if (rawIndex)
|
|
|
+ idMap[rawIndex] = `${propsName}[${idsInValue.size + 1}].value`
|
|
|
+ } else {
|
|
|
+ propsName = `[${[rawValue || ((rawKey || rawIndex) && '_'), rawKey || (rawIndex && '__'), rawIndex].filter(Boolean).join(', ')}]`
|
|
|
+ }
|
|
|
+
|
|
|
+ const blockFn = context.withId(
|
|
|
+ () => genBlock(render, context, [propsName]),
|
|
|
+ idMap,
|
|
|
+ )
|
|
|
+ exitScope()
|
|
|
+ return blockFn
|
|
|
+ }
|
|
|
+
|
|
|
+ function genSimpleIdMap() {
|
|
|
+ const idMap: Record<string, null> = {}
|
|
|
+ if (rawKey) idMap[rawKey] = null
|
|
|
+ if (rawIndex) idMap[rawIndex] = null
|
|
|
+ idsInValue.forEach(id => (idMap[id] = null))
|
|
|
+ return idMap
|
|
|
+ }
|
|
|
+
|
|
|
+ function genCallback(expr: SimpleExpressionNode | undefined) {
|
|
|
+ if (!expr) return false
|
|
|
+ const res = context.withId(() => genExpression(expr, context), simpleIdMap)
|
|
|
+ return [
|
|
|
+ ...genMulti(
|
|
|
+ ['(', ')', ', '],
|
|
|
+ rawValue ? rawValue : rawKey || rawIndex ? '_' : undefined,
|
|
|
+ rawKey ? rawKey : rawIndex ? '__' : undefined,
|
|
|
+ rawIndex,
|
|
|
+ ),
|
|
|
+ ' => (',
|
|
|
+ ...res,
|
|
|
+ ')',
|
|
|
+ ]
|
|
|
+ }
|
|
|
}
|