From c22363425ae246ccbb8418342e94edfa270d93e5 Mon Sep 17 00:00:00 2001 From: xdm <35987327+xiaodemen@users.noreply.github.com> Date: Mon, 23 Oct 2023 15:11:13 +0800 Subject: [PATCH] fix(patch): clone insert hooks to avoid being mutated during iteration (#12905) --- src/core/vdom/patch.ts | 7 +++- .../modules/vdom/patch/edge-cases.spec.ts | 38 +++++++++++++++++++ 2 files changed, 43 insertions(+), 2 deletions(-) diff --git a/src/core/vdom/patch.ts b/src/core/vdom/patch.ts index d0594863e3b..173840787bc 100644 --- a/src/core/vdom/patch.ts +++ b/src/core/vdom/patch.ts @@ -878,8 +878,11 @@ export function createPatchFunction(backend) { const insert = ancestor.data.hook.insert if (insert.merged) { // start at index 1 to avoid re-invoking component mounted hook - for (let i = 1; i < insert.fns.length; i++) { - insert.fns[i]() + // clone insert hooks to avoid being mutated during iteration. + // e.g. for customed directives under transition group. + const cloned = insert.fns.slice(1) + for (let i = 0; i < cloned.length; i++) { + cloned[i]() } } } else { diff --git a/test/unit/modules/vdom/patch/edge-cases.spec.ts b/test/unit/modules/vdom/patch/edge-cases.spec.ts index f9295533b1e..1b27f2b630c 100644 --- a/test/unit/modules/vdom/patch/edge-cases.spec.ts +++ b/test/unit/modules/vdom/patch/edge-cases.spec.ts @@ -467,4 +467,42 @@ describe('vdom patch: edge cases', () => { vm.visible = false vm.$nextTick(done) }) + + it('should call directive\'s inserted hook correctly when template root is changed', done => { + let insertCalled = false + const vm = new Vue({ + data: { + isOn: false + }, + components: { + 'v-switch': { + props: { + on: Boolean + }, + template: ` +
On
+
Off
` + } + }, + directives: { + foo: { + inserted() { + insertCalled = true + } + } + }, + template: ` + + + + ` + }).$mount() + + vm.isOn = true + insertCalled = false + waitForUpdate(() => { + expect(vm.$el.textContent).toMatch('On') + expect(insertCalled).toBe(true) + }).then(done) + }) })