feat(experimental): support ref transform for sfc normal <script>
This commit is contained in:
@@ -1,43 +0,0 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`<script setup> ref sugar $ unwrapping 1`] = `
|
||||
"import { ref, shallowRef } from 'vue'
|
||||
|
||||
export default {
|
||||
setup(__props, { expose }) {
|
||||
expose()
|
||||
|
||||
let foo = (ref())
|
||||
let a = (ref(1))
|
||||
let b = (shallowRef({
|
||||
count: 0
|
||||
}))
|
||||
let c = () => {}
|
||||
let d
|
||||
|
||||
return { foo, a, b, c, d, ref, shallowRef }
|
||||
}
|
||||
|
||||
}"
|
||||
`;
|
||||
|
||||
exports[`<script setup> ref sugar $ref & $shallowRef declarations 1`] = `
|
||||
"import { ref as _ref, shallowRef as _shallowRef } from 'vue'
|
||||
|
||||
export default {
|
||||
setup(__props, { expose }) {
|
||||
expose()
|
||||
|
||||
let foo = _ref()
|
||||
let a = _ref(1)
|
||||
let b = _shallowRef({
|
||||
count: 0
|
||||
})
|
||||
let c = () => {}
|
||||
let d
|
||||
|
||||
return { foo, a, b, c, d }
|
||||
}
|
||||
|
||||
}"
|
||||
`;
|
||||
@@ -0,0 +1,80 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`sfc ref transform $ unwrapping 1`] = `
|
||||
"import { ref, shallowRef } from 'vue'
|
||||
|
||||
export default {
|
||||
setup(__props, { expose }) {
|
||||
expose()
|
||||
|
||||
let foo = (ref())
|
||||
let a = (ref(1))
|
||||
let b = (shallowRef({
|
||||
count: 0
|
||||
}))
|
||||
let c = () => {}
|
||||
let d
|
||||
|
||||
return { foo, a, b, c, d, ref, shallowRef }
|
||||
}
|
||||
|
||||
}"
|
||||
`;
|
||||
|
||||
exports[`sfc ref transform $ref & $shallowRef declarations 1`] = `
|
||||
"import { ref as _ref, shallowRef as _shallowRef } from 'vue'
|
||||
|
||||
export default {
|
||||
setup(__props, { expose }) {
|
||||
expose()
|
||||
|
||||
let foo = _ref()
|
||||
let a = _ref(1)
|
||||
let b = _shallowRef({
|
||||
count: 0
|
||||
})
|
||||
let c = () => {}
|
||||
let d
|
||||
|
||||
return { foo, a, b, c, d }
|
||||
}
|
||||
|
||||
}"
|
||||
`;
|
||||
|
||||
exports[`sfc ref transform usage in normal <script> 1`] = `
|
||||
"import { ref as _ref } from 'vue'
|
||||
|
||||
export default {
|
||||
setup() {
|
||||
let count = _ref(0)
|
||||
const inc = () => count.value++
|
||||
return ({ count })
|
||||
}
|
||||
}
|
||||
"
|
||||
`;
|
||||
|
||||
exports[`sfc ref transform usage with normal <script> + <script setup> 1`] = `
|
||||
"import { ref as _ref } from 'vue'
|
||||
|
||||
let a = _ref(0)
|
||||
let c = _ref(0)
|
||||
|
||||
export default {
|
||||
setup(__props, { expose }) {
|
||||
expose()
|
||||
|
||||
let b = _ref(0)
|
||||
let c = 0
|
||||
function change() {
|
||||
a.value++
|
||||
b.value++
|
||||
c++
|
||||
}
|
||||
|
||||
return { a, c, b, change }
|
||||
}
|
||||
|
||||
}"
|
||||
`;
|
||||
@@ -3,13 +3,13 @@ import { compileSFCScript as compile, assertCode } from './utils'
|
||||
|
||||
// this file only tests integration with SFC - main test case for the ref
|
||||
// transform can be found in <root>/packages/ref-transform/__tests__
|
||||
describe('<script setup> ref sugar', () => {
|
||||
function compileWithRefSugar(src: string) {
|
||||
describe('sfc ref transform', () => {
|
||||
function compileWithRefTransform(src: string) {
|
||||
return compile(src, { refSugar: true })
|
||||
}
|
||||
|
||||
test('$ unwrapping', () => {
|
||||
const { content, bindings } = compileWithRefSugar(`<script setup>
|
||||
const { content, bindings } = compileWithRefTransform(`<script setup>
|
||||
import { ref, shallowRef } from 'vue'
|
||||
let foo = $(ref())
|
||||
let a = $(ref(1))
|
||||
@@ -46,7 +46,7 @@ describe('<script setup> ref sugar', () => {
|
||||
})
|
||||
|
||||
test('$ref & $shallowRef declarations', () => {
|
||||
const { content, bindings } = compileWithRefSugar(`<script setup>
|
||||
const { content, bindings } = compileWithRefTransform(`<script setup>
|
||||
let foo = $ref()
|
||||
let a = $ref(1)
|
||||
let b = $shallowRef({
|
||||
@@ -81,6 +81,58 @@ describe('<script setup> ref sugar', () => {
|
||||
})
|
||||
})
|
||||
|
||||
test('usage in normal <script>', () => {
|
||||
const { content } = compileWithRefTransform(`<script>
|
||||
export default {
|
||||
setup() {
|
||||
let count = $ref(0)
|
||||
const inc = () => count++
|
||||
return $$({ count })
|
||||
}
|
||||
}
|
||||
</script>`)
|
||||
expect(content).not.toMatch(`$ref(0)`)
|
||||
expect(content).toMatch(`import { ref as _ref } from 'vue'`)
|
||||
expect(content).toMatch(`let count = _ref(0)`)
|
||||
expect(content).toMatch(`count.value++`)
|
||||
expect(content).toMatch(`return ({ count })`)
|
||||
assertCode(content)
|
||||
})
|
||||
|
||||
test('usage with normal <script> + <script setup>', () => {
|
||||
const { content, bindings } = compileWithRefTransform(`<script>
|
||||
let a = $ref(0)
|
||||
let c = $ref(0)
|
||||
</script>
|
||||
<script setup>
|
||||
let b = $ref(0)
|
||||
let c = 0
|
||||
function change() {
|
||||
a++
|
||||
b++
|
||||
c++
|
||||
}
|
||||
</script>`)
|
||||
// should dedupe helper imports
|
||||
expect(content).toMatch(`import { ref as _ref } from 'vue'`)
|
||||
|
||||
expect(content).toMatch(`let a = _ref(0)`)
|
||||
expect(content).toMatch(`let b = _ref(0)`)
|
||||
|
||||
// root level ref binding declared in <script> should be inherited in <script setup>
|
||||
expect(content).toMatch(`a.value++`)
|
||||
expect(content).toMatch(`b.value++`)
|
||||
// c shadowed
|
||||
expect(content).toMatch(`c++`)
|
||||
assertCode(content)
|
||||
expect(bindings).toStrictEqual({
|
||||
a: BindingTypes.SETUP_REF,
|
||||
b: BindingTypes.SETUP_REF,
|
||||
c: BindingTypes.SETUP_REF,
|
||||
change: BindingTypes.SETUP_CONST
|
||||
})
|
||||
})
|
||||
|
||||
describe('errors', () => {
|
||||
test('defineProps/Emit() referencing ref declarations', () => {
|
||||
expect(() =>
|
||||
@@ -165,12 +165,34 @@ export function compileScript(
|
||||
return script
|
||||
}
|
||||
try {
|
||||
const scriptAst = _parse(script.content, {
|
||||
let content = script.content
|
||||
let map = script.map
|
||||
const scriptAst = _parse(content, {
|
||||
plugins,
|
||||
sourceType: 'module'
|
||||
}).program.body
|
||||
const bindings = analyzeScriptBindings(scriptAst)
|
||||
let content = script.content
|
||||
}).program
|
||||
const bindings = analyzeScriptBindings(scriptAst.body)
|
||||
if (enableRefTransform && shouldTransformRef(content)) {
|
||||
const s = new MagicString(source)
|
||||
const startOffset = script.loc.start.offset
|
||||
const endOffset = script.loc.end.offset
|
||||
const { importedHelpers } = transformRefAST(scriptAst, s, startOffset)
|
||||
if (importedHelpers.length) {
|
||||
s.prepend(
|
||||
`import { ${importedHelpers
|
||||
.map(h => `${h} as _${h}`)
|
||||
.join(', ')} } from 'vue'\n`
|
||||
)
|
||||
}
|
||||
s.remove(0, startOffset)
|
||||
s.remove(endOffset, source.length)
|
||||
content = s.toString()
|
||||
map = s.generateMap({
|
||||
source: filename,
|
||||
hires: true,
|
||||
includeContent: true
|
||||
}) as unknown as RawSourceMap
|
||||
}
|
||||
if (cssVars.length) {
|
||||
content = rewriteDefault(content, `__default__`, plugins)
|
||||
content += genNormalScriptCssVarsCode(
|
||||
@@ -184,8 +206,9 @@ export function compileScript(
|
||||
return {
|
||||
...script,
|
||||
content,
|
||||
map,
|
||||
bindings,
|
||||
scriptAst
|
||||
scriptAst: scriptAst.body
|
||||
}
|
||||
} catch (e) {
|
||||
// silently fallback if parse fails since user may be using custom
|
||||
@@ -629,6 +652,23 @@ export function compileScript(
|
||||
walkDeclaration(node, setupBindings, userImportAlias)
|
||||
}
|
||||
}
|
||||
|
||||
// apply ref transform
|
||||
if (enableRefTransform && shouldTransformRef(script.content)) {
|
||||
warnExperimental(
|
||||
`ref sugar`,
|
||||
`https://github.com/vuejs/rfcs/discussions/369`
|
||||
)
|
||||
const { rootVars, importedHelpers } = transformRefAST(
|
||||
scriptAst,
|
||||
s,
|
||||
scriptStartOffset!
|
||||
)
|
||||
refBindings = rootVars
|
||||
for (const h of importedHelpers) {
|
||||
helperImports.add(h)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 2. parse <script setup> and walk over top level statements
|
||||
@@ -862,7 +902,7 @@ export function compileScript(
|
||||
}
|
||||
|
||||
// 3. Apply ref sugar transform
|
||||
if (enableRefTransform && shouldTransformRef(source)) {
|
||||
if (enableRefTransform && shouldTransformRef(scriptSetup.content)) {
|
||||
warnExperimental(
|
||||
`ref sugar`,
|
||||
`https://github.com/vuejs/rfcs/discussions/369`
|
||||
@@ -870,9 +910,10 @@ export function compileScript(
|
||||
const { rootVars, importedHelpers } = transformRefAST(
|
||||
scriptSetupAst,
|
||||
s,
|
||||
startOffset
|
||||
startOffset,
|
||||
refBindings
|
||||
)
|
||||
refBindings = rootVars
|
||||
refBindings = refBindings ? [...refBindings, ...rootVars] : rootVars
|
||||
for (const h of importedHelpers) {
|
||||
helperImports.add(h)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user