@@ -18,93 +18,128 @@ let ChildNodeNativeMethods;
1818 */
1919export default function ( internals , destination , builtIn ) {
2020 /**
21- * @param {...(!Node|string) } nodes
21+ * @param {!function(...(!Node|string)) } builtInMethod
22+ * @return {!function(...(!Node|string)) }
2223 */
23- destination [ 'before' ] = function ( ...nodes ) {
24- // TODO: Fix this for when one of `nodes` is a DocumentFragment!
25- const connectedBefore = /** @type {!Array<!Node> } */ ( nodes . filter ( node => {
26- // DocumentFragments are not connected and will not be added to the list.
27- return node instanceof Node && Utilities . isConnected ( node ) ;
28- } ) ) ;
29-
30- builtIn . before . apply ( this , nodes ) ;
24+ function beforeAfterPatch ( builtInMethod ) {
25+ return function ( ...nodes ) {
26+ /**
27+ * A copy of `nodes`, with any DocumentFragment replaced by its children.
28+ * @type {!Array<!Node> }
29+ */
30+ const flattenedNodes = [ ] ;
31+
32+ /**
33+ * Elements in `nodes` that were connected before this call.
34+ * @type {!Array<!Node> }
35+ */
36+ const connectedElements = [ ] ;
37+
38+ for ( var i = 0 ; i < nodes . length ; i ++ ) {
39+ const node = nodes [ i ] ;
3140
32- for ( let i = 0 ; i < connectedBefore . length ; i ++ ) {
33- internals . disconnectTree ( connectedBefore [ i ] ) ;
34- }
41+ if ( node instanceof Element && Utilities . isConnected ( node ) ) {
42+ connectedElements . push ( node ) ;
43+ }
3544
36- if ( Utilities . isConnected ( this ) ) {
37- for ( let i = 0 ; i < nodes . length ; i ++ ) {
38- const node = nodes [ i ] ;
39- if ( node instanceof Element ) {
40- internals . connectTree ( node ) ;
45+ if ( node instanceof DocumentFragment ) {
46+ for ( let child = node . firstChild ; child ; child = child . nextSibling ) {
47+ flattenedNodes . push ( child ) ;
48+ }
49+ } else {
50+ flattenedNodes . push ( node ) ;
4151 }
4252 }
43- }
44- } ;
4553
46- /**
47- * @param {...(!Node|string) } nodes
48- */
49- destination [ 'after' ] = function ( ...nodes ) {
50- // TODO: Fix this for when one of `nodes` is a DocumentFragment!
51- const connectedBefore = /** @type {!Array<!Node> } */ ( nodes . filter ( node => {
52- // DocumentFragments are not connected and will not be added to the list.
53- return node instanceof Node && Utilities . isConnected ( node ) ;
54- } ) ) ;
55-
56- builtIn . after . apply ( this , nodes ) ;
54+ builtInMethod . apply ( this , nodes ) ;
5755
58- for ( let i = 0 ; i < connectedBefore . length ; i ++ ) {
59- internals . disconnectTree ( connectedBefore [ i ] ) ;
60- }
56+ for ( let i = 0 ; i < connectedElements . length ; i ++ ) {
57+ internals . disconnectTree ( connectedElements [ i ] ) ;
58+ }
6159
62- if ( Utilities . isConnected ( this ) ) {
63- for ( let i = 0 ; i < nodes . length ; i ++ ) {
64- const node = nodes [ i ] ;
65- if ( node instanceof Element ) {
66- internals . connectTree ( node ) ;
60+ if ( Utilities . isConnected ( this ) ) {
61+ for ( let i = 0 ; i < flattenedNodes . length ; i ++ ) {
62+ const node = flattenedNodes [ i ] ;
63+ if ( node instanceof Element ) {
64+ internals . connectTree ( node ) ;
65+ }
6766 }
6867 }
69- }
70- } ;
71-
72- /**
73- * @param {...(!Node|string) } nodes
74- */
75- destination [ 'replaceWith' ] = function ( ...nodes ) {
76- // TODO: Fix this for when one of `nodes` is a DocumentFragment!
77- const connectedBefore = /** @type {!Array<!Node> } */ ( nodes . filter ( node => {
78- // DocumentFragments are not connected and will not be added to the list.
79- return node instanceof Node && Utilities . isConnected ( node ) ;
80- } ) ) ;
68+ } ;
69+ }
70+
71+ if ( builtIn . before !== undefined ) {
72+ Utilities . setPropertyUnchecked ( destination , 'before' , beforeAfterPatch ( builtIn . before ) ) ;
73+ }
74+
75+ if ( builtIn . before !== undefined ) {
76+ Utilities . setPropertyUnchecked ( destination , 'after' , beforeAfterPatch ( builtIn . after ) ) ;
77+ }
78+
79+ if ( builtIn . replaceWith !== undefined ) {
80+ Utilities . setPropertyUnchecked ( destination , 'replaceWith' ,
81+ /**
82+ * @param {...(!Node|string) } nodes
83+ */
84+ function ( ...nodes ) {
85+ /**
86+ * A copy of `nodes`, with any DocumentFragment replaced by its children.
87+ * @type {!Array<!Node> }
88+ */
89+ const flattenedNodes = [ ] ;
90+
91+ /**
92+ * Elements in `nodes` that were connected before this call.
93+ * @type {!Array<!Node> }
94+ */
95+ const connectedElements = [ ] ;
96+
97+ for ( var i = 0 ; i < nodes . length ; i ++ ) {
98+ const node = nodes [ i ] ;
99+
100+ if ( node instanceof Element && Utilities . isConnected ( node ) ) {
101+ connectedElements . push ( node ) ;
102+ }
103+
104+ if ( node instanceof DocumentFragment ) {
105+ for ( let child = node . firstChild ; child ; child = child . nextSibling ) {
106+ flattenedNodes . push ( child ) ;
107+ }
108+ } else {
109+ flattenedNodes . push ( node ) ;
110+ }
111+ }
81112
82- const wasConnected = Utilities . isConnected ( this ) ;
113+ const wasConnected = Utilities . isConnected ( this ) ;
83114
84- builtIn . replaceWith . apply ( this , nodes ) ;
115+ builtIn . replaceWith . apply ( this , nodes ) ;
85116
86- for ( let i = 0 ; i < connectedBefore . length ; i ++ ) {
87- internals . disconnectTree ( connectedBefore [ i ] ) ;
88- }
117+ for ( let i = 0 ; i < connectedElements . length ; i ++ ) {
118+ internals . disconnectTree ( connectedElements [ i ] ) ;
119+ }
89120
90- if ( wasConnected ) {
91- internals . disconnectTree ( this ) ;
92- for ( let i = 0 ; i < nodes . length ; i ++ ) {
93- const node = nodes [ i ] ;
94- if ( node instanceof Element ) {
95- internals . connectTree ( node ) ;
121+ if ( wasConnected ) {
122+ internals . disconnectTree ( this ) ;
123+ for ( let i = 0 ; i < flattenedNodes . length ; i ++ ) {
124+ const node = flattenedNodes [ i ] ;
125+ if ( node instanceof Element ) {
126+ internals . connectTree ( node ) ;
127+ }
128+ }
96129 }
97- }
130+ } ) ;
98131 }
99- } ;
100132
101- destination [ 'remove' ] = function ( ) {
102- const wasConnected = Utilities . isConnected ( this ) ;
133+ if ( builtIn . remove !== undefined ) {
134+ Utilities . setPropertyUnchecked ( destination , 'remove' ,
135+ function ( ) {
136+ const wasConnected = Utilities . isConnected ( this ) ;
103137
104- builtIn . remove . call ( this ) ;
138+ builtIn . remove . call ( this ) ;
105139
106- if ( wasConnected ) {
107- internals . disconnectTree ( this ) ;
108- }
109- } ;
140+ if ( wasConnected ) {
141+ internals . disconnectTree ( this ) ;
142+ }
143+ } ) ;
144+ }
110145} ;
0 commit comments