diff --git a/packages/reactivity-transform/__tests__/__snapshots__/reactivityTransform.spec.ts.snap b/packages/reactivity-transform/__tests__/__snapshots__/reactivityTransform.spec.ts.snap index 26490ac9d9d..7d3542bb64f 100644 --- a/packages/reactivity-transform/__tests__/__snapshots__/reactivityTransform.spec.ts.snap +++ b/packages/reactivity-transform/__tests__/__snapshots__/reactivityTransform.spec.ts.snap @@ -163,7 +163,20 @@ exports[`nested destructure 1`] = ` let __$temp_2 = (useBar()), d = _toRef(__$temp_2.c, 0), e = _toRef(__$temp_2.c, 1); - console.log(b.value, d.value, e.value) + let __$temp_3 = (useBaz()), + f = _toRef(__$temp_3, 0), + g = _toRef(__$temp_3[1], 'g'), + h = _toRef(__$temp_3[2], 1); + console.log(b.value, d.value, e.value, f.value, g.value, h.value) + " +`; + +exports[`nested destructure w/ mid-path default values 1`] = ` +"import { toRef as _toRef } from 'vue' + + let __$temp_1 = (useFoo()), + b = _toRef((__$temp_1[0].a || { b: 123 }), 'b'); + console.log(b.value) " `; diff --git a/packages/reactivity-transform/__tests__/reactivityTransform.spec.ts b/packages/reactivity-transform/__tests__/reactivityTransform.spec.ts index 5255be6ba8b..05fe34943ca 100644 --- a/packages/reactivity-transform/__tests__/reactivityTransform.spec.ts +++ b/packages/reactivity-transform/__tests__/reactivityTransform.spec.ts @@ -283,12 +283,26 @@ test('nested destructure', () => { const { code, rootRefs } = transform(` let [{ a: { b }}] = $(useFoo()) let { c: [d, e] } = $(useBar()) - console.log(b, d, e) + let [f, { g }, [ , h ]] = $(useBaz()) + console.log(b, d, e, f, g, h) `) expect(code).toMatch(`b = _toRef(__$temp_1[0].a, 'b')`) expect(code).toMatch(`d = _toRef(__$temp_2.c, 0)`) expect(code).toMatch(`e = _toRef(__$temp_2.c, 1)`) - expect(rootRefs).toStrictEqual(['b', 'd', 'e']) + expect(code).toMatch(`f = _toRef(__$temp_3, 0)`) + expect(code).toMatch(`g = _toRef(__$temp_3[1], 'g')`) + expect(code).toMatch(`h = _toRef(__$temp_3[2], 1)`) + expect(rootRefs).toStrictEqual(['b', 'd', 'e', 'f', 'g', 'h']) + assertCode(code) +}) + +test('nested destructure w/ mid-path default values', () => { + const { code, rootRefs } = transform(` + let [{ a: { b } = { b: 123 }}] = $(useFoo()) + console.log(b) + `) + expect(code).toMatch(`b = _toRef((__$temp_1[0].a || { b: 123 }), 'b')`) + expect(rootRefs).toStrictEqual(['b']) assertCode(code) }) diff --git a/packages/reactivity-transform/src/reactivityTransform.ts b/packages/reactivity-transform/src/reactivityTransform.ts index f1d5d8916fd..6f3966fb265 100644 --- a/packages/reactivity-transform/src/reactivityTransform.ts +++ b/packages/reactivity-transform/src/reactivityTransform.ts @@ -368,15 +368,16 @@ export function transformAST( isConst: boolean, tempVar?: string, path: PathSegment[] = [] - ) { + ): boolean { if (!tempVar) { tempVar = genTempVar() // const { x } = $(useFoo()) --> const __$temp_1 = useFoo() s.overwrite(pattern.start! + offset, pattern.end! + offset, tempVar) } - let nameId: Identifier | undefined + let didBind = false for (const p of pattern.properties) { + let nameId: Identifier | undefined let key: Expression | string | undefined let defaultValue: Expression | undefined if (p.type === 'ObjectProperty') { @@ -400,30 +401,34 @@ export function transformAST( // { foo: bar } nameId = p.value } else if (p.value.type === 'ObjectPattern') { - processRefObjectPattern(p.value, call, isConst, tempVar, [ - ...path, - key - ]) + didBind = + processRefObjectPattern(p.value, call, isConst, tempVar, [ + ...path, + key + ]) || didBind } else if (p.value.type === 'ArrayPattern') { - processRefArrayPattern(p.value, call, isConst, tempVar, [ - ...path, - key - ]) + didBind = + processRefArrayPattern(p.value, call, isConst, tempVar, [ + ...path, + key + ]) || didBind } else if (p.value.type === 'AssignmentPattern') { if (p.value.left.type === 'Identifier') { // { foo: bar = 1 } nameId = p.value.left defaultValue = p.value.right } else if (p.value.left.type === 'ObjectPattern') { - processRefObjectPattern(p.value.left, call, isConst, tempVar, [ - ...path, - [key, p.value.right] - ]) + didBind = + processRefObjectPattern(p.value.left, call, isConst, tempVar, [ + ...path, + [key, p.value.right] + ]) || didBind } else if (p.value.left.type === 'ArrayPattern') { - processRefArrayPattern(p.value.left, call, isConst, tempVar, [ - ...path, - [key, p.value.right] - ]) + didBind = + processRefArrayPattern(p.value.left, call, isConst, tempVar, [ + ...path, + [key, p.value.right] + ]) || didBind } else { // MemberExpression case is not possible here, ignore } @@ -449,11 +454,14 @@ export function transformAST( 'toRef' )}(${source}, ${keyStr}${defaultStr})` ) + + didBind = true } } - if (nameId) { + if (didBind && path.length === 0) { s.appendLeft(call.end! + offset, ';') } + return didBind } function processRefArrayPattern( @@ -462,17 +470,19 @@ export function transformAST( isConst: boolean, tempVar?: string, path: PathSegment[] = [] - ) { + ): boolean { if (!tempVar) { // const [x] = $(useFoo()) --> const __$temp_1 = useFoo() tempVar = genTempVar() s.overwrite(pattern.start! + offset, pattern.end! + offset, tempVar) } - let nameId: Identifier | undefined + let didBind = false for (let i = 0; i < pattern.elements.length; i++) { const e = pattern.elements[i] if (!e) continue + + let nameId: Identifier | undefined let defaultValue: Expression | undefined if (e.type === 'Identifier') { // [a] --> [__a] @@ -485,9 +495,13 @@ export function transformAST( // [...a] error(`reactivity destructure does not support rest elements.`, e) } else if (e.type === 'ObjectPattern') { - processRefObjectPattern(e, call, isConst, tempVar, [...path, i]) + didBind = + processRefObjectPattern(e, call, isConst, tempVar, [...path, i]) || + didBind } else if (e.type === 'ArrayPattern') { - processRefArrayPattern(e, call, isConst, tempVar, [...path, i]) + didBind = + processRefArrayPattern(e, call, isConst, tempVar, [...path, i]) || + didBind } if (nameId) { registerRefBinding(nameId, isConst) @@ -500,11 +514,14 @@ export function transformAST( 'toRef' )}(${source}, ${i}${defaultStr})` ) + + didBind = true } } - if (nameId) { + if (didBind && path.length === 0) { s.appendLeft(call.end! + offset, ';') } + return didBind } type PathSegmentAtom = Expression | string | number