|
@@ -6,14 +6,11 @@ import {
|
|
|
INDENT_END,
|
|
INDENT_END,
|
|
|
INDENT_START,
|
|
INDENT_START,
|
|
|
NEWLINE,
|
|
NEWLINE,
|
|
|
|
|
+ buildCodeFragment,
|
|
|
} from '../generate'
|
|
} from '../generate'
|
|
|
-import type { ForIRNode } from '../ir'
|
|
|
|
|
-import {
|
|
|
|
|
- NewlineType,
|
|
|
|
|
- type SimpleExpressionNode,
|
|
|
|
|
- walkIdentifiers,
|
|
|
|
|
-} from '@vue/compiler-dom'
|
|
|
|
|
-import type { ArrowFunctionExpression } from '@babel/types'
|
|
|
|
|
|
|
+import type { ForIRNode, IREffect } from '../ir'
|
|
|
|
|
+import { genOperations } from './operation'
|
|
|
|
|
+import { NewlineType } from '@vue/compiler-dom'
|
|
|
|
|
|
|
|
export function genFor(
|
|
export function genFor(
|
|
|
oper: ForIRNode,
|
|
oper: ForIRNode,
|
|
@@ -22,63 +19,73 @@ export function genFor(
|
|
|
const { call, vaporHelper } = context
|
|
const { call, vaporHelper } = context
|
|
|
const { source, value, key, render } = oper
|
|
const { source, value, key, render } = oper
|
|
|
|
|
|
|
|
|
|
+ const rawValue = value && value.content
|
|
|
const rawKey = key && key.content
|
|
const rawKey = key && key.content
|
|
|
|
|
+
|
|
|
const sourceExpr = ['() => (', ...genExpression(source, context), ')']
|
|
const sourceExpr = ['() => (', ...genExpression(source, context), ')']
|
|
|
- const valueIds = value ? extractParams(value) : new Set<string>()
|
|
|
|
|
- const keyIds = key ? extractParams(key) : new Set<string>()
|
|
|
|
|
- const ids = [...valueIds, ...keyIds]
|
|
|
|
|
|
|
+ let updateFn = '_updateEffect'
|
|
|
|
|
+ context.genEffect = genEffectInFor
|
|
|
|
|
|
|
|
- let preamble: CodeFragment[] = []
|
|
|
|
|
- if (value || rawKey) {
|
|
|
|
|
- const assignment: CodeFragment[] = ['let ', ids.join(', ')]
|
|
|
|
|
|
|
+ const idMap: Record<string, string> = {}
|
|
|
|
|
+ if (rawValue) idMap[rawValue] = `_block.s[0]`
|
|
|
|
|
+ if (rawKey) idMap[rawKey] = `_block.s[1]`
|
|
|
|
|
|
|
|
- preamble = [
|
|
|
|
|
- NEWLINE,
|
|
|
|
|
- ...assignment,
|
|
|
|
|
- NEWLINE,
|
|
|
|
|
- ...call(vaporHelper('renderEffect'), [
|
|
|
|
|
- '() => {',
|
|
|
|
|
- INDENT_START,
|
|
|
|
|
- NEWLINE,
|
|
|
|
|
- '(',
|
|
|
|
|
- '[',
|
|
|
|
|
- value && [value.content, NewlineType.None, value.loc],
|
|
|
|
|
- rawKey && ', ',
|
|
|
|
|
- rawKey && [rawKey, NewlineType.None, key.loc],
|
|
|
|
|
- '] = _block.s',
|
|
|
|
|
- ');',
|
|
|
|
|
- INDENT_END,
|
|
|
|
|
- NEWLINE,
|
|
|
|
|
- '}',
|
|
|
|
|
- ]),
|
|
|
|
|
- ]
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ const blockRet = (): CodeFragment[] => [
|
|
|
|
|
+ `[n${render.dynamic.id!}, ${updateFn}]`,
|
|
|
|
|
+ ]
|
|
|
|
|
|
|
|
- const blockRet: CodeFragment[] = [`n${render.dynamic.id!}`]
|
|
|
|
|
const blockFn = context.withId(
|
|
const blockFn = context.withId(
|
|
|
- () => genBlockFunction(render, context, ['_block'], preamble, blockRet),
|
|
|
|
|
- ids,
|
|
|
|
|
|
|
+ () => genBlockFunction(render, context, ['_block'], blockRet),
|
|
|
|
|
+ idMap,
|
|
|
)
|
|
)
|
|
|
|
|
|
|
|
|
|
+ context.genEffect = undefined
|
|
|
|
|
+
|
|
|
return [
|
|
return [
|
|
|
NEWLINE,
|
|
NEWLINE,
|
|
|
`const n${oper.id} = `,
|
|
`const n${oper.id} = `,
|
|
|
...call(vaporHelper('createFor'), sourceExpr, blockFn),
|
|
...call(vaporHelper('createFor'), sourceExpr, blockFn),
|
|
|
]
|
|
]
|
|
|
-}
|
|
|
|
|
|
|
|
|
|
-function extractParams(node: SimpleExpressionNode) {
|
|
|
|
|
- const ids = new Set<string>()
|
|
|
|
|
- if (node.ast === null || node.ast === false) {
|
|
|
|
|
- ids.add(node.content)
|
|
|
|
|
- } else {
|
|
|
|
|
- walkIdentifiers(
|
|
|
|
|
- node.ast as ArrowFunctionExpression,
|
|
|
|
|
- (id, parent, parentStack, isReference, isLocal) => {
|
|
|
|
|
- if (isLocal) ids.add(id.name)
|
|
|
|
|
- },
|
|
|
|
|
- true,
|
|
|
|
|
- )
|
|
|
|
|
|
|
+ function genEffectInFor(effects: IREffect[]): CodeFragment[] {
|
|
|
|
|
+ if (!effects.length) {
|
|
|
|
|
+ updateFn = '() => {}'
|
|
|
|
|
+ return []
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ const [frag, push] = buildCodeFragment(INDENT_START)
|
|
|
|
|
+ // const [value, key] = _block.s
|
|
|
|
|
+ if (rawValue || rawKey) {
|
|
|
|
|
+ push(
|
|
|
|
|
+ NEWLINE,
|
|
|
|
|
+ 'const ',
|
|
|
|
|
+ '[',
|
|
|
|
|
+ rawValue && [rawValue, NewlineType.None, value.loc],
|
|
|
|
|
+ rawKey && ', ',
|
|
|
|
|
+ rawKey && [rawKey, NewlineType.None, key.loc],
|
|
|
|
|
+ '] = _block.s',
|
|
|
|
|
+ )
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ const idMap: Record<string, string | null> = {}
|
|
|
|
|
+ if (value) idMap[value.content] = null
|
|
|
|
|
+ if (key) idMap[key.content] = null
|
|
|
|
|
+ context.withId(() => {
|
|
|
|
|
+ effects.forEach(effect =>
|
|
|
|
|
+ push(...genOperations(effect.operations, context)),
|
|
|
|
|
+ )
|
|
|
|
|
+ }, idMap)
|
|
|
|
|
+
|
|
|
|
|
+ push(INDENT_END)
|
|
|
|
|
+
|
|
|
|
|
+ return [
|
|
|
|
|
+ NEWLINE,
|
|
|
|
|
+ `const ${updateFn} = () => {`,
|
|
|
|
|
+ ...frag,
|
|
|
|
|
+ NEWLINE,
|
|
|
|
|
+ '}',
|
|
|
|
|
+ NEWLINE,
|
|
|
|
|
+ `${vaporHelper('renderEffect')}(${updateFn})`,
|
|
|
|
|
+ ]
|
|
|
}
|
|
}
|
|
|
- return ids
|
|
|
|
|
}
|
|
}
|