From 1f6a1102aa09960f76a9af2872ef01e7da8538e3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=B8=89=E5=92=B2=E6=99=BA=E5=AD=90=20Kevin=20Deng?= Date: Wed, 28 Feb 2024 15:19:24 +0800 Subject: [PATCH 01/72] test: clean snapshot --- .../__snapshots__/importUsageCheck.spec.ts.snap | 15 --------------- 1 file changed, 15 deletions(-) diff --git a/packages/compiler-sfc/__tests__/compileScript/__snapshots__/importUsageCheck.spec.ts.snap b/packages/compiler-sfc/__tests__/compileScript/__snapshots__/importUsageCheck.spec.ts.snap index cfdbf5f45..764d120a7 100644 --- a/packages/compiler-sfc/__tests__/compileScript/__snapshots__/importUsageCheck.spec.ts.snap +++ b/packages/compiler-sfc/__tests__/compileScript/__snapshots__/importUsageCheck.spec.ts.snap @@ -79,21 +79,6 @@ return { get FooBar() { return FooBar }, get foo() { return foo }, get bar() { r })" `; -exports[`import namespace 1`] = ` -"import { defineComponent as _defineComponent } from 'vue' -import * as Foo from './foo' - -export default /*#__PURE__*/_defineComponent({ - setup(__props, { expose: __expose }) { - __expose(); - - -return { get Foo() { return Foo } } -} - -})" -`; - exports[`js template string interpolations 1`] = ` "import { defineComponent as _defineComponent } from 'vue' import { VAR, VAR2, VAR3 } from './x' From 7c97778aec1e3513035e5df265e1b8a7801f6106 Mon Sep 17 00:00:00 2001 From: edison Date: Wed, 28 Feb 2024 19:05:22 +0800 Subject: [PATCH 02/72] fix(suspense): ensure nested suspense patching if in fallback state (#10417) close #10415 --- .../__tests__/components/Suspense.spec.ts | 139 ++++++++++++++++-- .../runtime-core/src/components/Suspense.ts | 6 +- 2 files changed, 132 insertions(+), 13 deletions(-) diff --git a/packages/runtime-core/__tests__/components/Suspense.spec.ts b/packages/runtime-core/__tests__/components/Suspense.spec.ts index fd1913b2c..a448972e1 100644 --- a/packages/runtime-core/__tests__/components/Suspense.spec.ts +++ b/packages/runtime-core/__tests__/components/Suspense.spec.ts @@ -54,6 +54,18 @@ describe('Suspense', () => { } } + const RouterView = { + setup(_: any, { slots }: any) { + const route = inject('route') as any + const depth = inject('depth', 0) + provide('depth', depth + 1) + return () => { + const current = route.value[depth] + return slots.default({ Component: current })[0] + } + }, + } + test('fallback content', async () => { const Async = defineAsyncComponent({ render() { @@ -1041,18 +1053,6 @@ describe('Suspense', () => { // #10098 test('switching branches w/ nested suspense', async () => { - const RouterView = { - setup(_: any, { slots }: any) { - const route = inject('route') as any - const depth = inject('depth', 0) - provide('depth', depth + 1) - return () => { - const current = route.value[depth] - return slots.default({ Component: current })[0] - } - }, - } - const OuterB = defineAsyncComponent({ setup: () => { return () => @@ -1132,6 +1132,121 @@ describe('Suspense', () => { expect(serializeInner(root)).toBe(`
innerA
`) }) + // #10415 + test('nested suspense (w/ suspensible) switch several times before parent suspense resolve', async () => { + const OuterA = defineAsyncComponent({ + setup: () => { + return () => + h(RouterView, null, { + default: ({ Component }: any) => [ + h(Suspense, null, { + default: () => h(Component), + }), + ], + }) + }, + }) + + const InnerA = defineAsyncComponent({ + setup: () => { + return () => h('div', 'innerA') + }, + }) + + const route = shallowRef([OuterA, InnerA]) + const InnerB = defineAsyncComponent( + { + setup: () => { + return () => h('div', 'innerB') + }, + }, + 5, + ) + + const InnerB1 = defineAsyncComponent( + { + setup: () => { + return () => h('div', 'innerB1') + }, + }, + 5, + ) + + const InnerB2 = defineAsyncComponent( + { + setup: () => { + return () => h('div', 'innerB2') + }, + }, + 5, + ) + + const OuterB = defineAsyncComponent( + { + setup() { + nextTick(async () => { + await new Promise(resolve => setTimeout(resolve, 1)) + route.value = [OuterB, InnerB1] + }) + + nextTick(async () => { + await new Promise(resolve => setTimeout(resolve, 1)) + route.value = [OuterB, InnerB2] + }) + + return () => + h(RouterView, null, { + default: ({ Component }: any) => [ + h( + Suspense, + { suspensible: true }, + { + default: () => h(Component), + }, + ), + ], + }) + }, + }, + 5, + ) + + const Comp = { + setup() { + provide('route', route) + return () => + h(RouterView, null, { + default: ({ Component }: any) => [ + h(Suspense, null, { + default: () => h(Component), + }), + ], + }) + }, + } + + const root = nodeOps.createElement('div') + render(h(Comp), root) + await Promise.all(deps) + await nextTick() + expect(serializeInner(root)).toBe(``) + + await Promise.all(deps) + await nextTick() + expect(serializeInner(root)).toBe(`
innerA
`) + + deps.length = 0 + + route.value = [OuterB, InnerB] + await nextTick() + + await Promise.all(deps) + await Promise.all(deps) + await Promise.all(deps) + await nextTick() + expect(serializeInner(root)).toBe(`
innerB2
`) + }) + test('branch switch to 3rd branch before resolve', async () => { const calls: string[] = [] diff --git a/packages/runtime-core/src/components/Suspense.ts b/packages/runtime-core/src/components/Suspense.ts index 65b05c3dd..9461d7fec 100644 --- a/packages/runtime-core/src/components/Suspense.ts +++ b/packages/runtime-core/src/components/Suspense.ts @@ -99,7 +99,11 @@ export const SuspenseImpl = { // 2. mounting along with the pendingBranch of parentSuspense // it is necessary to skip the current patch to avoid multiple mounts // of inner components. - if (parentSuspense && parentSuspense.deps > 0) { + if ( + parentSuspense && + parentSuspense.deps > 0 && + !n1.suspense!.isInFallback + ) { n2.suspense = n1.suspense! n2.suspense.vnode = n2 n2.el = n1.el From bc37258caa2f6f67f4554ab8587aca3798d92124 Mon Sep 17 00:00:00 2001 From: edison Date: Wed, 28 Feb 2024 19:06:18 +0800 Subject: [PATCH 03/72] fix(warning): stringify args in warn handler (#10414) close #10409 --- packages/runtime-core/src/warning.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/runtime-core/src/warning.ts b/packages/runtime-core/src/warning.ts index 16928387d..c3b2ebbd0 100644 --- a/packages/runtime-core/src/warning.ts +++ b/packages/runtime-core/src/warning.ts @@ -45,7 +45,7 @@ export function warn(msg: string, ...args: any[]) { instance, ErrorCodes.APP_WARN_HANDLER, [ - msg + args.join(''), + msg + args.map(a => a.toString?.() ?? JSON.stringify(a)).join(''), instance && instance.proxy, trace .map( From b3f8b5a4e700d4c47a146b6040882287d180f6cb Mon Sep 17 00:00:00 2001 From: Doctor Wu <44631608+Doctor-wu@users.noreply.github.com> Date: Wed, 28 Feb 2024 19:07:12 +0800 Subject: [PATCH 04/72] fix(runtime-dom): avoid unset option's value (#10416) close #10412 re-fix #10396 --- packages/runtime-dom/__tests__/patchProps.spec.ts | 12 ++++++++++++ packages/runtime-dom/src/modules/props.ts | 8 ++++---- 2 files changed, 16 insertions(+), 4 deletions(-) diff --git a/packages/runtime-dom/__tests__/patchProps.spec.ts b/packages/runtime-dom/__tests__/patchProps.spec.ts index 7c356f1a6..61dd98513 100644 --- a/packages/runtime-dom/__tests__/patchProps.spec.ts +++ b/packages/runtime-dom/__tests__/patchProps.spec.ts @@ -291,6 +291,18 @@ describe('runtime-dom: props patching', () => { expect(el.value).toBe('baz') }) + test('init empty value for option', () => { + const root = document.createElement('div') + render( + h('select', { value: 'foo' }, [h('option', { value: '' }, 'foo')]), + root, + ) + const select = root.children[0] as HTMLSelectElement + const option = select.children[0] as HTMLOptionElement + expect(select.value).toBe('') + expect(option.value).toBe('') + }) + // #8780 test('embedded tag with width and height', () => { // Width and height of some embedded element such as img、video、source、canvas diff --git a/packages/runtime-dom/src/modules/props.ts b/packages/runtime-dom/src/modules/props.ts index e9b3bca35..c4bb4987b 100644 --- a/packages/runtime-dom/src/modules/props.ts +++ b/packages/runtime-dom/src/modules/props.ts @@ -34,20 +34,20 @@ export function patchDOMProp( // custom elements may use _value internally !tag.includes('-') ) { - // store value as _value as well since - // non-string values will be stringified. - el._value = value // #4956: