Merge ac43f5ecd2
into 88ef97ffd3
This commit is contained in:
commit
1087cb3951
|
@ -32,3 +32,25 @@ export function render(_ctx, $props, $emit, $attrs, $slots) {
|
||||||
return n0
|
return n0
|
||||||
}"
|
}"
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
exports[`compiler: expression > update expression 1`] = `
|
||||||
|
"import { child as _child, toDisplayString as _toDisplayString, setText as _setText, setProp as _setProp, renderEffect as _renderEffect, template as _template } from 'vue';
|
||||||
|
const t0 = _template("<div> </div>", true)
|
||||||
|
|
||||||
|
export function render(_ctx) {
|
||||||
|
const n1 = t0()
|
||||||
|
const n0 = _child(n1)
|
||||||
|
const x1 = _child(n1)
|
||||||
|
_renderEffect(() => {
|
||||||
|
const _String = String
|
||||||
|
const _foo = _ctx.foo
|
||||||
|
|
||||||
|
_setText(n0, _toDisplayString(_String(_foo.id++)) + " " + _toDisplayString(_foo) + " " + _toDisplayString(_ctx.bar))
|
||||||
|
_setText(x1, _toDisplayString(_String(_foo.id++)) + " " + _toDisplayString(_foo) + " " + _toDisplayString(_ctx.bar))
|
||||||
|
_setProp(n1, "id", _String(_foo.id++))
|
||||||
|
_setProp(n1, "foo", _foo)
|
||||||
|
_setProp(n1, "bar", _ctx.bar++)
|
||||||
|
})
|
||||||
|
return n1
|
||||||
|
}"
|
||||||
|
`;
|
||||||
|
|
|
@ -21,7 +21,14 @@ export function render(_ctx) {
|
||||||
const _setTemplateRef = _createTemplateRefSetter()
|
const _setTemplateRef = _createTemplateRefSetter()
|
||||||
const n0 = t0()
|
const n0 = t0()
|
||||||
let r0
|
let r0
|
||||||
_renderEffect(() => r0 = _setTemplateRef(n0, bar => _ctx.foo = bar, r0))
|
_renderEffect(() => {
|
||||||
|
const _foo = _ctx.foo
|
||||||
|
r0 = _setTemplateRef(n0, bar => {
|
||||||
|
_foo.value = bar
|
||||||
|
;({ baz: _ctx.baz } = bar)
|
||||||
|
console.log(_foo.value, _ctx.baz)
|
||||||
|
}, r0)
|
||||||
|
})
|
||||||
return n0
|
return n0
|
||||||
}"
|
}"
|
||||||
`;
|
`;
|
||||||
|
|
|
@ -1,9 +1,15 @@
|
||||||
import { BindingTypes } from '@vue/compiler-dom'
|
import { BindingTypes } from '@vue/compiler-dom'
|
||||||
import { transformChildren, transformText } from '../../src'
|
import {
|
||||||
|
transformChildren,
|
||||||
|
transformElement,
|
||||||
|
transformText,
|
||||||
|
transformVBind,
|
||||||
|
} from '../../src'
|
||||||
import { makeCompile } from './_utils'
|
import { makeCompile } from './_utils'
|
||||||
|
|
||||||
const compileWithExpression = makeCompile({
|
const compileWithExpression = makeCompile({
|
||||||
nodeTransforms: [transformChildren, transformText],
|
nodeTransforms: [transformElement, transformChildren, transformText],
|
||||||
|
directiveTransforms: { bind: transformVBind },
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('compiler: expression', () => {
|
describe('compiler: expression', () => {
|
||||||
|
@ -31,4 +37,14 @@ describe('compiler: expression', () => {
|
||||||
expect(code).toMatchSnapshot()
|
expect(code).toMatchSnapshot()
|
||||||
expect(code).contains(`$props['bar']`)
|
expect(code).contains(`$props['bar']`)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
test('update expression', () => {
|
||||||
|
const { code } = compileWithExpression(`
|
||||||
|
<div :id="String(foo.id++)" :foo="foo" :bar="bar++">
|
||||||
|
{{ String(foo.id++) }} {{ foo }} {{ bar }}
|
||||||
|
</div>
|
||||||
|
`)
|
||||||
|
expect(code).toMatchSnapshot()
|
||||||
|
expect(code).contains(`_String(_foo.id++)`)
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|
|
@ -83,7 +83,11 @@ describe('compiler: template ref transform', () => {
|
||||||
|
|
||||||
test('function ref', () => {
|
test('function ref', () => {
|
||||||
const { ir, code } = compileWithTransformRef(
|
const { ir, code } = compileWithTransformRef(
|
||||||
`<div :ref="bar => foo = bar" />`,
|
`<div :ref="bar => {
|
||||||
|
foo.value = bar
|
||||||
|
;({ baz } = bar)
|
||||||
|
console.log(foo.value, baz)
|
||||||
|
}" />`,
|
||||||
)
|
)
|
||||||
expect(ir.block.dynamic.children[0]).toMatchObject({
|
expect(ir.block.dynamic.children[0]).toMatchObject({
|
||||||
id: 0,
|
id: 0,
|
||||||
|
@ -103,7 +107,6 @@ describe('compiler: template ref transform', () => {
|
||||||
type: IRNodeTypes.SET_TEMPLATE_REF,
|
type: IRNodeTypes.SET_TEMPLATE_REF,
|
||||||
element: 0,
|
element: 0,
|
||||||
value: {
|
value: {
|
||||||
content: 'bar => foo = bar',
|
|
||||||
isStatic: false,
|
isStatic: false,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -112,7 +115,11 @@ describe('compiler: template ref transform', () => {
|
||||||
])
|
])
|
||||||
expect(code).toMatchSnapshot()
|
expect(code).toMatchSnapshot()
|
||||||
expect(code).contains('const _setTemplateRef = _createTemplateRefSetter()')
|
expect(code).contains('const _setTemplateRef = _createTemplateRefSetter()')
|
||||||
expect(code).contains('_setTemplateRef(n0, bar => _ctx.foo = bar, r0)')
|
expect(code).contains(`_setTemplateRef(n0, bar => {
|
||||||
|
_foo.value = bar
|
||||||
|
;({ baz: _ctx.baz } = bar)
|
||||||
|
console.log(_foo.value, _ctx.baz)
|
||||||
|
}, r0)`)
|
||||||
})
|
})
|
||||||
|
|
||||||
test('ref + v-if', () => {
|
test('ref + v-if', () => {
|
||||||
|
|
|
@ -244,8 +244,13 @@ export function processExpressions(
|
||||||
expressions: SimpleExpressionNode[],
|
expressions: SimpleExpressionNode[],
|
||||||
): DeclarationResult {
|
): DeclarationResult {
|
||||||
// analyze variables
|
// analyze variables
|
||||||
const { seenVariable, variableToExpMap, expToVariableMap, seenIdentifier } =
|
const {
|
||||||
analyzeExpressions(expressions)
|
seenVariable,
|
||||||
|
variableToExpMap,
|
||||||
|
expToVariableMap,
|
||||||
|
seenIdentifier,
|
||||||
|
updatedVariable,
|
||||||
|
} = analyzeExpressions(expressions)
|
||||||
|
|
||||||
// process repeated identifiers and member expressions
|
// process repeated identifiers and member expressions
|
||||||
// e.g., `foo[baz]` will be transformed into `foo_baz`
|
// e.g., `foo[baz]` will be transformed into `foo_baz`
|
||||||
|
@ -255,6 +260,7 @@ export function processExpressions(
|
||||||
variableToExpMap,
|
variableToExpMap,
|
||||||
expToVariableMap,
|
expToVariableMap,
|
||||||
seenIdentifier,
|
seenIdentifier,
|
||||||
|
updatedVariable,
|
||||||
)
|
)
|
||||||
|
|
||||||
// process duplicate expressions after identifier and member expression handling.
|
// process duplicate expressions after identifier and member expression handling.
|
||||||
|
@ -263,6 +269,8 @@ export function processExpressions(
|
||||||
context,
|
context,
|
||||||
expressions,
|
expressions,
|
||||||
varDeclarations,
|
varDeclarations,
|
||||||
|
updatedVariable,
|
||||||
|
expToVariableMap,
|
||||||
)
|
)
|
||||||
|
|
||||||
return genDeclarations([...varDeclarations, ...expDeclarations], context)
|
return genDeclarations([...varDeclarations, ...expDeclarations], context)
|
||||||
|
@ -273,11 +281,13 @@ function analyzeExpressions(expressions: SimpleExpressionNode[]) {
|
||||||
const variableToExpMap = new Map<string, Set<SimpleExpressionNode>>()
|
const variableToExpMap = new Map<string, Set<SimpleExpressionNode>>()
|
||||||
const expToVariableMap = new Map<SimpleExpressionNode, string[]>()
|
const expToVariableMap = new Map<SimpleExpressionNode, string[]>()
|
||||||
const seenIdentifier = new Set<string>()
|
const seenIdentifier = new Set<string>()
|
||||||
|
const updatedVariable = new Set<string>()
|
||||||
|
|
||||||
const registerVariable = (
|
const registerVariable = (
|
||||||
name: string,
|
name: string,
|
||||||
exp: SimpleExpressionNode,
|
exp: SimpleExpressionNode,
|
||||||
isIdentifier: boolean,
|
isIdentifier: boolean,
|
||||||
|
parentStack: Node[] = [],
|
||||||
) => {
|
) => {
|
||||||
if (isIdentifier) seenIdentifier.add(name)
|
if (isIdentifier) seenIdentifier.add(name)
|
||||||
seenVariable[name] = (seenVariable[name] || 0) + 1
|
seenVariable[name] = (seenVariable[name] || 0) + 1
|
||||||
|
@ -286,6 +296,13 @@ function analyzeExpressions(expressions: SimpleExpressionNode[]) {
|
||||||
(variableToExpMap.get(name) || new Set()).add(exp),
|
(variableToExpMap.get(name) || new Set()).add(exp),
|
||||||
)
|
)
|
||||||
expToVariableMap.set(exp, (expToVariableMap.get(exp) || []).concat(name))
|
expToVariableMap.set(exp, (expToVariableMap.get(exp) || []).concat(name))
|
||||||
|
if (
|
||||||
|
parentStack.some(
|
||||||
|
p => p.type === 'UpdateExpression' || p.type === 'AssignmentExpression',
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
updatedVariable.add(name)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const exp of expressions) {
|
for (const exp of expressions) {
|
||||||
|
@ -299,14 +316,20 @@ function analyzeExpressions(expressions: SimpleExpressionNode[]) {
|
||||||
const memberExp = extractMemberExpression(parent, name => {
|
const memberExp = extractMemberExpression(parent, name => {
|
||||||
registerVariable(name, exp, true)
|
registerVariable(name, exp, true)
|
||||||
})
|
})
|
||||||
registerVariable(memberExp, exp, false)
|
registerVariable(memberExp, exp, false, parentStack)
|
||||||
} else if (!parentStack.some(isMemberExpression)) {
|
} else if (!parentStack.some(isMemberExpression)) {
|
||||||
registerVariable(currentNode.name, exp, true)
|
registerVariable(currentNode.name, exp, true, parentStack)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
return { seenVariable, seenIdentifier, variableToExpMap, expToVariableMap }
|
return {
|
||||||
|
seenVariable,
|
||||||
|
seenIdentifier,
|
||||||
|
variableToExpMap,
|
||||||
|
expToVariableMap,
|
||||||
|
updatedVariable,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function processRepeatedVariables(
|
function processRepeatedVariables(
|
||||||
|
@ -315,9 +338,11 @@ function processRepeatedVariables(
|
||||||
variableToExpMap: Map<string, Set<SimpleExpressionNode>>,
|
variableToExpMap: Map<string, Set<SimpleExpressionNode>>,
|
||||||
expToVariableMap: Map<SimpleExpressionNode, string[]>,
|
expToVariableMap: Map<SimpleExpressionNode, string[]>,
|
||||||
seenIdentifier: Set<string>,
|
seenIdentifier: Set<string>,
|
||||||
|
updatedVariable: Set<string>,
|
||||||
): DeclarationValue[] {
|
): DeclarationValue[] {
|
||||||
const declarations: DeclarationValue[] = []
|
const declarations: DeclarationValue[] = []
|
||||||
for (const [name, exps] of variableToExpMap) {
|
for (const [name, exps] of variableToExpMap) {
|
||||||
|
if (updatedVariable.has(name)) continue
|
||||||
if (seenVariable[name] > 1 && exps.size > 0) {
|
if (seenVariable[name] > 1 && exps.size > 0) {
|
||||||
const isIdentifier = seenIdentifier.has(name)
|
const isIdentifier = seenIdentifier.has(name)
|
||||||
const varName = isIdentifier ? name : genVarName(name)
|
const varName = isIdentifier ? name : genVarName(name)
|
||||||
|
@ -409,12 +434,19 @@ function processRepeatedExpressions(
|
||||||
context: CodegenContext,
|
context: CodegenContext,
|
||||||
expressions: SimpleExpressionNode[],
|
expressions: SimpleExpressionNode[],
|
||||||
varDeclarations: DeclarationValue[],
|
varDeclarations: DeclarationValue[],
|
||||||
|
updatedVariable: Set<string>,
|
||||||
|
expToVariableMap: Map<SimpleExpressionNode, string[]>,
|
||||||
): DeclarationValue[] {
|
): DeclarationValue[] {
|
||||||
const declarations: DeclarationValue[] = []
|
const declarations: DeclarationValue[] = []
|
||||||
const seenExp = expressions.reduce(
|
const seenExp = expressions.reduce(
|
||||||
(acc, exp) => {
|
(acc, exp) => {
|
||||||
|
const variables = expToVariableMap.get(exp)
|
||||||
// only handle expressions that are not identifiers
|
// only handle expressions that are not identifiers
|
||||||
if (exp.ast && exp.ast.type !== 'Identifier') {
|
if (
|
||||||
|
exp.ast &&
|
||||||
|
exp.ast.type !== 'Identifier' &&
|
||||||
|
!(variables && variables.some(v => updatedVariable.has(v)))
|
||||||
|
) {
|
||||||
acc[exp.content] = (acc[exp.content] || 0) + 1
|
acc[exp.content] = (acc[exp.content] || 0) + 1
|
||||||
}
|
}
|
||||||
return acc
|
return acc
|
||||||
|
|
Loading…
Reference in New Issue