Skip to content

Commit 82937dc

Browse files
committed
insertBefore bugfix
1 parent f1ebaca commit 82937dc

File tree

2 files changed

+96
-8
lines changed

2 files changed

+96
-8
lines changed

src/component.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
1-
const freeze = (object, property, value) => {
1+
export const freeze = (object, property, value) => {
22
Object.defineProperty(object, property, {
33
configurable: true,
44
get() { return value; },
55
set(v) { console.warn(`tried to set frozen property ${property} with ${v}`) }
66
});
77
};
88

9-
const unfreeze = (object, property, value = null) => {
9+
export const unfreeze = (object, property, value = null) => {
1010
Object.defineProperty(object, property, {
1111
configurable: true,
1212
writable: true,
@@ -45,7 +45,7 @@ export default {
4545
// use document fragment to improve efficiency
4646
let tpl = document.createDocumentFragment()
4747
tpl.appendChild(head)
48-
48+
4949
Array.from(container.childNodes)
5050
.forEach(node => {
5151
// container.appendChild(node, true)

src/index.js

Lines changed: 93 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,104 @@
1-
import component from './component'
2-
import ssr from './ssr'
1+
import component, { freeze, unfreeze } from './component'
2+
import ssr from './ssr'
33

44
export const Fragment = component
55

66
export const SSR = ssr
77

88
export const Plugin = {
9-
install: function(Vue) {
9+
install: function (Vue) {
10+
const orgRemoveChild = window.Node.prototype.removeChild
11+
window.Node.prototype.removeChild = function (node) {
12+
if (this.__isFragment) {
13+
if (this.parentNode) {
14+
let ret = this.parentNode.removeChild(node)
15+
unfreeze(node, 'parentNode')
16+
return ret
17+
}
18+
} else if (node.__isFragment && node.__isMounted) {
19+
while (node.__head.nextSibling !== node.__tail) orgRemoveChild.call(this, node.__head.nextSibling)
20+
21+
orgRemoveChild.call(this, node.__head)
22+
orgRemoveChild.call(this, node.__tail)
23+
let prev = node.__head.previousSibling,
24+
next = node.__tail.nextSibling
25+
if (prev) freeze(prev, 'nextSibling', next)
26+
if (next) freeze(next, 'previousSibling', prev)
27+
28+
unfreeze(node, 'parentNode')
29+
return node
30+
} else {
31+
let prev = node.previousSibling,
32+
next = node.nextSibling
33+
let ret = orgRemoveChild.call(this, node)
34+
if (prev) freeze(prev, 'nextSibling', next)
35+
if (next) freeze(next, 'previousSibling', prev)
36+
return ret
37+
}
38+
}
39+
40+
const orgInsertBefore = window.Node.prototype.insertBefore
41+
window.Node.prototype.insertBefore = function (node, ref, inFragment = false) {
42+
let realRef = !!ref && !!ref.__isFragment && !!ref.__isMounted ? ref.__head : ref
43+
if (this.__isFragment) {
44+
let notFrChild = !node.hasOwnProperty('__isFragmentChild__'),
45+
freezeParent = !inFragment || notFrChild
46+
47+
notFrChild && freeze(node, '__isFragmentChild__', true)
48+
let ret = this.parentNode ? this.parentNode.insertBefore(node, ref) : orgInsertBefore.call(this, node, realRef)
49+
freezeParent && freeze(node, 'parentNode', this)
50+
51+
return ret
52+
} else if (node.__isFragment && node.__isMounted) {
53+
if (node === ref) {
54+
console.error('something must be wrong')
55+
return
56+
}
57+
freeze(node, 'parentNode', this)
58+
if (node.previousSibling) freeze(node.previousSibling, 'nextSibling', node.nextSibling)
59+
if (node.nextSibling) freeze(node.nextSibling, 'previousSibling', node.previousSibling)
60+
freeze(node, 'nextSibling', ref)
61+
freeze(node, 'previousSibling', ref.previousSibling)
62+
if (ref.previousSibling) freeze(ref.previousSibling, 'nextSibling', node)
63+
freeze(ref, 'previousSibling', node)
64+
65+
let tpl = document.createDocumentFragment(),
66+
ele = node.__head
67+
while (ele !== node.__tail) {
68+
tpl.appendChild(ele)
69+
ele = ele.nextSibling
70+
}
71+
tpl.appendChild(node.__tail)
72+
orgInsertBefore.call(this, tpl, realRef)
73+
return node
74+
} else {
75+
return orgInsertBefore.call(this, node, realRef)
76+
}
77+
}
78+
79+
const orgAppendChild = window.Node.prototype.appendChild
80+
window.Node.prototype.appendChild = function (node, inFragment = false) {
81+
if (this.__isFragment) {
82+
if (this.parentNode) {
83+
let notFrChild = !node.hasOwnProperty('__isFragmentChild__'),
84+
freezeParent = !inFragment || notFrChild
85+
86+
notFrChild && freeze(node, '__isFragmentChild__', true)
87+
let ret = this.parentNode.insertBefore(node, this.__tail, inFragment)
88+
freezeParent && freeze(node, 'parentNode', this)
89+
90+
return ret
91+
}
92+
} else {
93+
return orgAppendChild.call(this, node)
94+
}
95+
}
1096
Vue.component('Fragment', component)
11-
}
97+
},
1298
}
1399

14100
export default {
15-
Fragment, Plugin, SSR
101+
Fragment,
102+
Plugin,
103+
SSR,
16104
}

0 commit comments

Comments
 (0)