mirror of https://github.com/vuejs/core.git
fix(compiler-sfc): fix sfc template unref rewrite for class instantiation
close #6483 close #6491
This commit is contained in:
parent
fda51925f4
commit
ae60a91cc2
|
@ -146,6 +146,19 @@ export function isInDestructureAssignment(
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function isInNewExpression(parentStack: Node[]): boolean {
|
||||||
|
let i = parentStack.length
|
||||||
|
while (i--) {
|
||||||
|
const p = parentStack[i]
|
||||||
|
if (p.type === 'NewExpression') {
|
||||||
|
return true
|
||||||
|
} else if (p.type !== 'MemberExpression') {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
export function walkFunctionParams(
|
export function walkFunctionParams(
|
||||||
node: Function,
|
node: Function,
|
||||||
onIdent: (id: Identifier) => void,
|
onIdent: (id: Identifier) => void,
|
||||||
|
|
|
@ -19,6 +19,7 @@ import {
|
||||||
} from '../ast'
|
} from '../ast'
|
||||||
import {
|
import {
|
||||||
isInDestructureAssignment,
|
isInDestructureAssignment,
|
||||||
|
isInNewExpression,
|
||||||
isStaticProperty,
|
isStaticProperty,
|
||||||
isStaticPropertyKey,
|
isStaticPropertyKey,
|
||||||
walkIdentifiers,
|
walkIdentifiers,
|
||||||
|
@ -131,6 +132,11 @@ export function processExpression(
|
||||||
// ({ x } = y)
|
// ({ x } = y)
|
||||||
const isDestructureAssignment =
|
const isDestructureAssignment =
|
||||||
parent && isInDestructureAssignment(parent, parentStack)
|
parent && isInDestructureAssignment(parent, parentStack)
|
||||||
|
const isNewExpression = parent && isInNewExpression(parentStack)
|
||||||
|
const wrapWithUnref = (raw: string) => {
|
||||||
|
const wrapped = `${context.helperString(UNREF)}(${raw})`
|
||||||
|
return isNewExpression ? `(${wrapped})` : wrapped
|
||||||
|
}
|
||||||
|
|
||||||
if (
|
if (
|
||||||
isConst(type) ||
|
isConst(type) ||
|
||||||
|
@ -147,7 +153,7 @@ export function processExpression(
|
||||||
// that assumes the value to be a ref for more efficiency
|
// that assumes the value to be a ref for more efficiency
|
||||||
return isAssignmentLVal || isUpdateArg || isDestructureAssignment
|
return isAssignmentLVal || isUpdateArg || isDestructureAssignment
|
||||||
? `${raw}.value`
|
? `${raw}.value`
|
||||||
: `${context.helperString(UNREF)}(${raw})`
|
: wrapWithUnref(raw)
|
||||||
} else if (type === BindingTypes.SETUP_LET) {
|
} else if (type === BindingTypes.SETUP_LET) {
|
||||||
if (isAssignmentLVal) {
|
if (isAssignmentLVal) {
|
||||||
// let binding.
|
// let binding.
|
||||||
|
@ -190,7 +196,7 @@ export function processExpression(
|
||||||
// for now
|
// for now
|
||||||
return raw
|
return raw
|
||||||
} else {
|
} else {
|
||||||
return `${context.helperString(UNREF)}(${raw})`
|
return wrapWithUnref(raw)
|
||||||
}
|
}
|
||||||
} else if (type === BindingTypes.PROPS) {
|
} else if (type === BindingTypes.PROPS) {
|
||||||
// use __props which is generated by compileScript so in ts mode
|
// use __props which is generated by compileScript so in ts mode
|
||||||
|
|
|
@ -1028,6 +1028,26 @@ return (_ctx, _cache) => {
|
||||||
}"
|
}"
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
exports[`SFC compile <script setup> > inlineTemplate mode > unref + new expression 1`] = `
|
||||||
|
"import { unref as _unref, toDisplayString as _toDisplayString, createElementVNode as _createElementVNode, Fragment as _Fragment, openBlock as _openBlock, createElementBlock as _createElementBlock } from "vue"
|
||||||
|
|
||||||
|
import Foo from './foo'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
setup(__props) {
|
||||||
|
|
||||||
|
|
||||||
|
return (_ctx, _cache) => {
|
||||||
|
return (_openBlock(), _createElementBlock(_Fragment, null, [
|
||||||
|
_createElementVNode("div", null, _toDisplayString(new (_unref(Foo))()), 1 /* TEXT */),
|
||||||
|
_createElementVNode("div", null, _toDisplayString(new (_unref(Foo)).Bar()), 1 /* TEXT */)
|
||||||
|
], 64 /* STABLE_FRAGMENT */))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}"
|
||||||
|
`;
|
||||||
|
|
||||||
exports[`SFC compile <script setup> > inlineTemplate mode > v-model codegen 1`] = `
|
exports[`SFC compile <script setup> > inlineTemplate mode > v-model codegen 1`] = `
|
||||||
"import { vModelText as _vModelText, createElementVNode as _createElementVNode, withDirectives as _withDirectives, unref as _unref, isRef as _isRef, Fragment as _Fragment, openBlock as _openBlock, createElementBlock as _createElementBlock } from "vue"
|
"import { vModelText as _vModelText, createElementVNode as _createElementVNode, withDirectives as _withDirectives, unref as _unref, isRef as _isRef, Fragment as _Fragment, openBlock as _openBlock, createElementBlock as _createElementBlock } from "vue"
|
||||||
|
|
||||||
|
|
|
@ -650,6 +650,24 @@ describe('SFC compile <script setup>', () => {
|
||||||
),
|
),
|
||||||
).not.toThrowError()
|
).not.toThrowError()
|
||||||
})
|
})
|
||||||
|
|
||||||
|
test('unref + new expression', () => {
|
||||||
|
const { content } = compile(
|
||||||
|
`
|
||||||
|
<script setup>
|
||||||
|
import Foo from './foo'
|
||||||
|
</script>
|
||||||
|
<template>
|
||||||
|
<div>{{ new Foo() }}</div>
|
||||||
|
<div>{{ new Foo.Bar() }}</div>
|
||||||
|
</template>
|
||||||
|
`,
|
||||||
|
{ inlineTemplate: true },
|
||||||
|
)
|
||||||
|
expect(content).toMatch(`new (_unref(Foo))()`)
|
||||||
|
expect(content).toMatch(`new (_unref(Foo)).Bar()`)
|
||||||
|
assertCode(content)
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('with TypeScript', () => {
|
describe('with TypeScript', () => {
|
||||||
|
|
Loading…
Reference in New Issue