Skip to content

Commit 00b76d3

Browse files
committed
feat(sfc): support $shallowRef ref sugar
1 parent e42d779 commit 00b76d3

File tree

7 files changed

+46
-20
lines changed

7 files changed

+46
-20
lines changed

Diff for: packages/compiler-sfc/__tests__/__snapshots__/compileScriptRefSugar.spec.ts.snap

+3-3
Original file line numberDiff line numberDiff line change
@@ -33,16 +33,16 @@ return { a, b, c }
3333
}"
3434
`;
3535
36-
exports[`<script setup> ref sugar $ref declarations 1`] = `
37-
"import { ref as _ref } from 'vue'
36+
exports[`<script setup> ref sugar $ref & $shallowRef declarations 1`] = `
37+
"import { ref as _ref, shallowRef as _shallowRef } from 'vue'
3838
3939
export default {
4040
setup(__props, { expose }) {
4141
expose()
4242
4343
let foo = _ref()
4444
let a = _ref(1)
45-
let b = _ref({
45+
let b = _shallowRef({
4646
count: 0
4747
})
4848
let c = () => {}

Diff for: packages/compiler-sfc/__tests__/compileScriptRefSugar.spec.ts

+7-5
Original file line numberDiff line numberDiff line change
@@ -6,24 +6,26 @@ describe('<script setup> ref sugar', () => {
66
return compile(src, { refSugar: true })
77
}
88

9-
test('$ref declarations', () => {
9+
test('$ref & $shallowRef declarations', () => {
1010
const { content, bindings } = compileWithRefSugar(`<script setup>
1111
let foo = $ref()
1212
let a = $ref(1)
13-
let b = $ref({
13+
let b = $shallowRef({
1414
count: 0
1515
})
1616
let c = () => {}
1717
let d
1818
</script>`)
19-
expect(content).toMatch(`import { ref as _ref } from 'vue'`)
19+
expect(content).toMatch(
20+
`import { ref as _ref, shallowRef as _shallowRef } from 'vue'`
21+
)
2022
expect(content).not.toMatch(`$ref()`)
2123
expect(content).not.toMatch(`$ref(1)`)
22-
expect(content).not.toMatch(`$ref({`)
24+
expect(content).not.toMatch(`$shallowRef({`)
2325
expect(content).toMatch(`let foo = _ref()`)
2426
expect(content).toMatch(`let a = _ref(1)`)
2527
expect(content).toMatch(`
26-
let b = _ref({
28+
let b = _shallowRef({
2729
count: 0
2830
})
2931
`)

Diff for: packages/compiler-sfc/src/compileScript.ts

+18-11
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@ const DEFINE_EXPOSE = 'defineExpose'
6565
const WITH_DEFAULTS = 'withDefaults'
6666

6767
const $REF = `$ref`
68+
const $SHALLOW_REF = '$shallowRef'
6869
const $COMPUTED = `$computed`
6970
const $FROM_REFS = `$fromRefs`
7071
const $RAW = `$raw`
@@ -531,7 +532,12 @@ export function compileScript(
531532
}
532533

533534
function isRefSugarCall(callee: string) {
534-
return callee === $REF || callee === $COMPUTED || callee === $FROM_REFS
535+
return (
536+
callee === $REF ||
537+
callee === $COMPUTED ||
538+
callee === $FROM_REFS ||
539+
callee === $SHALLOW_REF
540+
)
535541
}
536542

537543
function processRefSugar(
@@ -558,24 +564,28 @@ export function compileScript(
558564

559565
const callee = (decl.init.callee as Identifier).name
560566
const start = decl.init.start! + startOffset
561-
if (callee === $REF) {
567+
if (callee === $REF || callee === $SHALLOW_REF) {
562568
if (statement.kind !== 'let') {
563-
error(`${$REF}() bindings can only be declared with let.`, decl)
569+
error(`${callee}() bindings can only be declared with let.`, decl)
564570
}
565571
if (decl.id.type !== 'Identifier') {
566572
error(
567-
`${$REF}() bindings cannot be used with destructuring. ` +
573+
`${callee}() bindings cannot be used with destructuring. ` +
568574
`If you are trying to destructure from an object of refs, ` +
569575
`use \`let { x } = $fromRefs(obj)\`.`,
570576
decl.id
571577
)
572578
}
573579
registerRefBinding(decl.id)
574-
s.overwrite(start, start + $REF.length, helper('ref'))
580+
s.overwrite(
581+
start,
582+
start + callee.length,
583+
helper(callee === $REF ? 'ref' : 'shallowRef')
584+
)
575585
} else if (callee === $COMPUTED) {
576586
if (decl.id.type !== 'Identifier') {
577587
error(
578-
`${$COMPUTED}() bindings cannot be used with destructuring.`,
588+
`${callee}() bindings cannot be used with destructuring.`,
579589
decl.id
580590
)
581591
}
@@ -584,7 +594,7 @@ export function compileScript(
584594
} else if (callee === $FROM_REFS) {
585595
if (!decl.id.type.endsWith('Pattern')) {
586596
error(
587-
`${$FROM_REFS}() declaration must be used with destructure patterns.`,
597+
`${callee}() declaration must be used with destructure patterns.`,
588598
decl
589599
)
590600
}
@@ -1124,10 +1134,7 @@ export function compileScript(
11241134
return false // skip walk
11251135
} else if (
11261136
parent &&
1127-
isCallOf(
1128-
node,
1129-
id => id === $REF || id === $FROM_REFS || id === $COMPUTED
1130-
) &&
1137+
isCallOf(node, isRefSugarCall) &&
11311138
(parent.type !== 'VariableDeclarator' || node !== parent.init)
11321139
) {
11331140
error(

Diff for: packages/runtime-core/src/helpers/refSugar.ts

+4
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,10 @@ import { Ref, UnwrapRef, ShallowUnwrapRef, ComputedRef } from '@vue/reactivity'
33
export function $ref<T>(arg: T | Ref<T>): UnwrapRef<T>
44
export function $ref() {}
55

6+
export function $shallowRef<T>(arg: T): T {
7+
return arg
8+
}
9+
610
declare const ComputedRefMarker: unique symbol
711
type ComputedRefValue<T> = T & { [ComputedRefMarker]?: any }
812

Diff for: packages/runtime-core/src/index.ts

+7-1
Original file line numberDiff line numberDiff line change
@@ -354,4 +354,10 @@ export const compatUtils = (
354354

355355
// Ref sugar macros ------------------------------------------------------------
356356
// for dts generation only
357-
export { $ref, $computed, $raw, $fromRefs } from './helpers/refSugar'
357+
export {
358+
$ref,
359+
$shallowRef,
360+
$computed,
361+
$raw,
362+
$fromRefs
363+
} from './helpers/refSugar'

Diff for: packages/runtime-core/types/scriptSetupHelpers.d.ts

+2
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ type _defineExpose = typeof defineExpose
66
type _withDefaults = typeof withDefaults
77

88
type _ref = typeof $ref
9+
type _shallowRef = typeof $shallowRef
910
type _computed = typeof $computed
1011
type _fromRefs = typeof $fromRefs
1112
type _raw = typeof $raw
@@ -17,6 +18,7 @@ declare global {
1718
const withDefaults: _withDefaults
1819

1920
const $ref: _ref
21+
const $shallowRef: _shallowRef
2022
const $computed: _computed
2123
const $fromRefs: _fromRefs
2224
const $raw: _raw

Diff for: test-dts/refSugar.test-d.ts

+5
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import {
22
expectType,
33
$ref,
4+
$shallowRef,
45
$computed,
56
$fromRefs,
67
$raw,
@@ -14,6 +15,10 @@ expectType<number>($ref(1))
1415
expectType<number>($ref(ref(1)))
1516
expectType<{ foo: number }>($ref({ foo: ref(1) }))
1617

18+
// $shallowRef
19+
expectType<number>($shallowRef(1))
20+
expectType<{ foo: Ref<number> }>($shallowRef({ foo: ref(1) }))
21+
1722
// $computed
1823
expectType<number>($computed(() => 1))
1924
let b = $ref(1)

0 commit comments

Comments
 (0)