11import {
22 remoteId ,
3+ setRemoteId ,
34 connectRemoteNode ,
45 disconnectRemoteNode ,
56 serializeRemoteNode ,
6- REMOTE_IDS ,
77} from './internals.ts' ;
88import {
99 ROOT_ID ,
@@ -32,7 +32,10 @@ import type {RemoteConnection, RemoteMutationRecord} from '../types.ts';
3232 * observer.observe(document.body);
3333 */
3434export class RemoteMutationObserver extends MutationObserver {
35- constructor ( private readonly connection : RemoteConnection ) {
35+ readonly connection : RemoteConnection ;
36+ readonly #observed: Set < Node > ;
37+
38+ constructor ( connection : RemoteConnection ) {
3639 super ( ( records ) => {
3740 const addedNodes : Node [ ] = [ ] ;
3841 const remoteRecords : RemoteMutationRecord [ ] = [ ] ;
@@ -102,6 +105,9 @@ export class RemoteMutationObserver extends MutationObserver {
102105
103106 connection . mutate ( remoteRecords ) ;
104107 } ) ;
108+
109+ this . connection = connection ;
110+ this . #observed = new Set ( ) ;
105111 }
106112
107113 /**
@@ -112,6 +118,18 @@ export class RemoteMutationObserver extends MutationObserver {
112118 observe (
113119 target : Node ,
114120 options ?: MutationObserverInit & {
121+ /**
122+ * The ID of the root element. If you do not provide an ID, a default value
123+ * considered to be the “root” element will be used. This means that its remote
124+ * attributes, properties, event listeners, and children will all be sent as the root
125+ * element to the remote receiver.
126+ *
127+ * You need to override the default behavior if you are wanting to observe a set of
128+ * nodes, and send each of them to the remote receiver. This may be needed when observing
129+ * a `DocumentFragment` or `<template>` element, which allow for multiple children.
130+ */
131+ id ?: string ;
132+
115133 /**
116134 * Whether to send the initial state of the tree to the mutation
117135 * callback.
@@ -121,24 +139,37 @@ export class RemoteMutationObserver extends MutationObserver {
121139 initial ?: boolean ;
122140 } ,
123141 ) {
124- REMOTE_IDS . set ( target , ROOT_ID ) ;
142+ const id = options ?. id ?? ROOT_ID ;
143+ setRemoteId ( target , id ) ;
144+ this . #observed. add ( target ) ;
125145
126146 if ( options ?. initial !== false && target . childNodes . length > 0 ) {
127- const records : RemoteMutationRecord [ ] = [ ] ;
128-
129- for ( let i = 0 ; i < target . childNodes . length ; i ++ ) {
130- const node = target . childNodes [ i ] ! ;
131- connectRemoteNode ( node , this . connection ) ;
132-
133- records . push ( [
134- MUTATION_TYPE_INSERT_CHILD ,
135- ROOT_ID ,
136- serializeRemoteNode ( node ) ,
137- i ,
147+ if ( id !== ROOT_ID ) {
148+ this . connection . mutate ( [
149+ [
150+ MUTATION_TYPE_INSERT_CHILD ,
151+ ROOT_ID ,
152+ serializeRemoteNode ( target ) ,
153+ this . #observed. size - 1 ,
154+ ] ,
138155 ] ) ;
139- }
156+ } else if ( target . childNodes . length > 0 ) {
157+ const records : RemoteMutationRecord [ ] = [ ] ;
158+
159+ for ( let i = 0 ; i < target . childNodes . length ; i ++ ) {
160+ const node = target . childNodes [ i ] ! ;
161+ connectRemoteNode ( node , this . connection ) ;
162+
163+ records . push ( [
164+ MUTATION_TYPE_INSERT_CHILD ,
165+ ROOT_ID ,
166+ serializeRemoteNode ( node ) ,
167+ i ,
168+ ] ) ;
169+ }
140170
141- this . connection . mutate ( records ) ;
171+ this . connection . mutate ( records ) ;
172+ }
142173 }
143174
144175 super . observe ( target , {
@@ -149,6 +180,30 @@ export class RemoteMutationObserver extends MutationObserver {
149180 ...options ,
150181 } ) ;
151182 }
183+
184+ disconnect ( { empty = false } : { empty ?: boolean } = { } ) {
185+ if ( empty && this . #observed. size > 0 ) {
186+ const records : RemoteMutationRecord [ ] = [ ] ;
187+
188+ for ( const node of this . #observed) {
189+ disconnectRemoteNode ( node ) ;
190+ const id = remoteId ( node ) ;
191+
192+ if ( id === ROOT_ID ) {
193+ for ( let i = 0 ; i < node . childNodes . length ; i ++ ) {
194+ records . push ( [ MUTATION_TYPE_REMOVE_CHILD , id , 0 ] ) ;
195+ }
196+ } else {
197+ records . push ( [ MUTATION_TYPE_REMOVE_CHILD , ROOT_ID , 0 ] ) ;
198+ }
199+ }
200+
201+ this . connection . mutate ( records ) ;
202+ }
203+
204+ this . #observed. clear ( ) ;
205+ super . disconnect ( ) ;
206+ }
152207}
153208
154209function indexOf ( node : Node , list : NodeList ) {
0 commit comments