Repository: vuejs/vue
Pull request: fix #5321 don't throw error when node gets relocated

<!--
Please make sure to read the Pull Request Guidelines:
https://github.com/vuejs/vue/blob/dev/.github/CONTRIBUTING.md#pull-request-guidelines
-->

<!-- PULL REQUEST TEMPLATE -->
<!-- (Update "[ ]" to "[x]" to check a box) -->

**What kind of change does this PR introduce?** (check at least one)

- [x] Bugfix
- [x] Feature
- [ ] Code style update
- [ ] Refactor
- [ ] Build-related changes
- [ ] Other, please describe:

**Does this PR introduce a breaking change?** (check one)

- [ ] Yes
- [x] No

If yes, please describe the impact and migration path for existing applications:

**The PR fulfills these requirements:**

- [x] It's submitted to the `dev` branch for v2.x (or to a previous version branch), _not_ the `master` branch
- [x] When resolving a specific issue, it's referenced in the PR's title (e.g. `fix #xxx[,#xxx]`, where "xxx" is the issue number)
- [x] All tests are passing: https://github.com/vuejs/vue/blob/dev/.github/CONTRIBUTING.md#development-setup
- [x] New/updated tests are included

If adding a **new feature**, the PR's description includes:
- [ ] A convincing reason for adding this feature (to avoid wasting your time, it's best to open a suggestion issue first and wait for approval before working on it)

**Other information:**
This PR fixes https://github.com/vuejs/vue/issues/5321
Reproduction link: https://jsfiddle.net/rstoenescu/uqsath1t/2/ (follow instructions in the Github issue)

Changed files:
filename: src/core/vdom/patch.js
patch: @@ -234,7 +234,9 @@ export function createPatchFunction (backend) {
   function insert (parent, elm, ref) {
     if (isDef(parent)) {
       if (isDef(ref)) {
-        nodeOps.insertBefore(parent, elm, ref)
+        if (ref.parentNode === parent) {
+          nodeOps.insertBefore(parent, elm, ref)
+        }
       } else {
         nodeOps.appendChild(parent, elm)
       }

filename: test/unit/features/component/component.spec.js
patch: @@ -366,4 +366,46 @@ describe('Component', () => {
       Vue.config.errorHandler = null
     }).then(done)
   })
+
+  it('relocates node without error', done => {
+    const el = document.createElement('div')
+    document.body.appendChild(el)
+    const target = document.createElement('div')
+    document.body.appendChild(target)
+
+    const Test = {
+      render (h) {
+        return h('div', { class: 'test' }, this.$slots.default)
+      },
+      mounted () {
+        target.appendChild(this.$el)
+      },
+      beforeDestroy () {
+        const parent = this.$el.parentNode
+        if (parent) {
+          parent.removeChild(this.$el)
+        }
+      }
+    }
+    const vm = new Vue({
+      data () {
+        return {
+          view: true
+        }
+      },
+      template: `<div><test v-if="view">Test</test></div>`,
+      components: {
+        test: Test
+      }
+    }).$mount(el)
+
+    expect(el.outerHTML).toBe('<div></div>')
+    expect(target.outerHTML).toBe('<div><div class="test">Test</div></div>')
+    vm.view = false
+    waitForUpdate(() => {
+      expect(el.outerHTML).toBe('<div></div>')
+      expect(target.outerHTML).toBe('<div></div>')
+      vm.$destroy()
+    }).then(done)
+  })
 })