@mml-io/networked-dom-document 0.1.2 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/build/index.js +100 -120
- package/build/index.js.map +3 -3
- package/package.json +3 -3
- package/src/EditableNetworkedDOM.ts +6 -16
- package/src/NetworkedDOM.ts +80 -95
- package/src/common.ts +8 -8
- package/src/diffing.ts +68 -68
package/build/index.js
CHANGED
|
@@ -32,7 +32,7 @@ __export(src_exports, {
|
|
|
32
32
|
EditableNetworkedDOM: () => EditableNetworkedDOM,
|
|
33
33
|
NetworkedDOM: () => NetworkedDOM,
|
|
34
34
|
defaultWebsocketSubProtocol: () => defaultWebsocketSubProtocol,
|
|
35
|
-
|
|
35
|
+
networkedDOMProtocolSubProtocol_v0_1: () => networkedDOMProtocolSubProtocol_v0_1
|
|
36
36
|
});
|
|
37
37
|
module.exports = __toCommonJS(src_exports);
|
|
38
38
|
|
|
@@ -43,31 +43,31 @@ var import_rfc6902 = require("rfc6902");
|
|
|
43
43
|
var rfc6902 = __toESM(require("rfc6902"));
|
|
44
44
|
var visibleToAttrName = "visible-to";
|
|
45
45
|
var hiddenFromAttrName = "hidden-from";
|
|
46
|
-
function
|
|
47
|
-
const
|
|
46
|
+
function diffFromApplicationOfStaticVirtualDOMMutationRecordToConnection(mutation, parentNode, connectionId, visibleNodesForConnection) {
|
|
47
|
+
const virtualDOMElement = mutation.target;
|
|
48
48
|
if (mutation.type === "attributes") {
|
|
49
|
-
const visible = visibleNodesForConnection.has(
|
|
49
|
+
const visible = visibleNodesForConnection.has(virtualDOMElement.nodeId);
|
|
50
50
|
if (!parentNode) {
|
|
51
51
|
throw new Error("Node has no parent");
|
|
52
52
|
}
|
|
53
53
|
const parentNodeId = parentNode.nodeId;
|
|
54
|
-
const shouldBeVisible = shouldShowNodeToConnectionId(
|
|
54
|
+
const shouldBeVisible = shouldShowNodeToConnectionId(virtualDOMElement, connectionId) && visibleNodesForConnection.has(parentNodeId);
|
|
55
55
|
const attributeName = mutation.attributeName;
|
|
56
56
|
if (visible && shouldBeVisible) {
|
|
57
57
|
let newValue = null;
|
|
58
|
-
if (
|
|
59
|
-
newValue =
|
|
58
|
+
if (virtualDOMElement.attributes[attributeName] !== void 0) {
|
|
59
|
+
newValue = virtualDOMElement.attributes[attributeName];
|
|
60
60
|
}
|
|
61
61
|
const diff = {
|
|
62
62
|
type: "attributeChange",
|
|
63
|
-
nodeId:
|
|
63
|
+
nodeId: virtualDOMElement.nodeId,
|
|
64
64
|
attribute: attributeName,
|
|
65
65
|
newValue
|
|
66
66
|
};
|
|
67
67
|
return diff;
|
|
68
68
|
} else if (!visible && shouldBeVisible) {
|
|
69
|
-
visibleNodesForConnection.add(
|
|
70
|
-
const index = parentNode.childNodes.indexOf(
|
|
69
|
+
visibleNodesForConnection.add(virtualDOMElement.nodeId);
|
|
70
|
+
const index = parentNode.childNodes.indexOf(virtualDOMElement);
|
|
71
71
|
if (index === -1) {
|
|
72
72
|
throw new Error("Node not found in parent's children");
|
|
73
73
|
}
|
|
@@ -80,7 +80,7 @@ function diffFromApplicationOfStaticVirtualDomMutationRecordToConnection(mutatio
|
|
|
80
80
|
);
|
|
81
81
|
}
|
|
82
82
|
const nodeDescription = describeNodeWithChildrenForConnectionId(
|
|
83
|
-
|
|
83
|
+
virtualDOMElement,
|
|
84
84
|
connectionId,
|
|
85
85
|
visibleNodesForConnection
|
|
86
86
|
);
|
|
@@ -96,27 +96,27 @@ function diffFromApplicationOfStaticVirtualDomMutationRecordToConnection(mutatio
|
|
|
96
96
|
};
|
|
97
97
|
return diff;
|
|
98
98
|
} else if (visible && !shouldBeVisible) {
|
|
99
|
-
removeNodeAndChildrenFromVisibleNodes(
|
|
99
|
+
removeNodeAndChildrenFromVisibleNodes(virtualDOMElement, visibleNodesForConnection);
|
|
100
100
|
const diff = {
|
|
101
101
|
type: "childrenChanged",
|
|
102
102
|
nodeId: parentNodeId,
|
|
103
103
|
previousNodeId: null,
|
|
104
104
|
addedNodes: [],
|
|
105
|
-
removedNodes: [
|
|
105
|
+
removedNodes: [virtualDOMElement.nodeId]
|
|
106
106
|
};
|
|
107
107
|
return diff;
|
|
108
108
|
} else if (!visible && !shouldBeVisible) {
|
|
109
109
|
return null;
|
|
110
110
|
}
|
|
111
111
|
}
|
|
112
|
-
if (!visibleNodesForConnection.has(
|
|
112
|
+
if (!visibleNodesForConnection.has(virtualDOMElement.nodeId)) {
|
|
113
113
|
return null;
|
|
114
114
|
}
|
|
115
115
|
if (mutation.type === "characterData") {
|
|
116
116
|
const diff = {
|
|
117
117
|
type: "textChanged",
|
|
118
|
-
nodeId:
|
|
119
|
-
text:
|
|
118
|
+
nodeId: virtualDOMElement.nodeId,
|
|
119
|
+
text: virtualDOMElement.textContent || ""
|
|
120
120
|
};
|
|
121
121
|
return diff;
|
|
122
122
|
}
|
|
@@ -124,9 +124,9 @@ function diffFromApplicationOfStaticVirtualDomMutationRecordToConnection(mutatio
|
|
|
124
124
|
let previousSibling = mutation.previousSibling;
|
|
125
125
|
let previousNodeId = null;
|
|
126
126
|
if (previousSibling) {
|
|
127
|
-
let previousIndex =
|
|
127
|
+
let previousIndex = virtualDOMElement.childNodes.indexOf(previousSibling);
|
|
128
128
|
while (previousIndex !== -1) {
|
|
129
|
-
previousSibling =
|
|
129
|
+
previousSibling = virtualDOMElement.childNodes[previousIndex];
|
|
130
130
|
if (visibleNodesForConnection.has(previousSibling.nodeId)) {
|
|
131
131
|
previousNodeId = previousSibling.nodeId;
|
|
132
132
|
break;
|
|
@@ -136,14 +136,14 @@ function diffFromApplicationOfStaticVirtualDomMutationRecordToConnection(mutatio
|
|
|
136
136
|
}
|
|
137
137
|
const diff = {
|
|
138
138
|
type: "childrenChanged",
|
|
139
|
-
nodeId:
|
|
139
|
+
nodeId: virtualDOMElement.nodeId,
|
|
140
140
|
previousNodeId,
|
|
141
141
|
addedNodes: [],
|
|
142
142
|
removedNodes: []
|
|
143
143
|
};
|
|
144
|
-
mutation.addedNodes.forEach((
|
|
144
|
+
mutation.addedNodes.forEach((childVirtualDOMElement) => {
|
|
145
145
|
const describedNode = describeNodeWithChildrenForConnectionId(
|
|
146
|
-
|
|
146
|
+
childVirtualDOMElement,
|
|
147
147
|
connectionId,
|
|
148
148
|
visibleNodesForConnection
|
|
149
149
|
);
|
|
@@ -152,10 +152,10 @@ function diffFromApplicationOfStaticVirtualDomMutationRecordToConnection(mutatio
|
|
|
152
152
|
}
|
|
153
153
|
diff.addedNodes.push(describedNode);
|
|
154
154
|
});
|
|
155
|
-
mutation.removedNodes.forEach((
|
|
156
|
-
if (visibleNodesForConnection.has(
|
|
157
|
-
removeNodeAndChildrenFromVisibleNodes(
|
|
158
|
-
diff.removedNodes.push(
|
|
155
|
+
mutation.removedNodes.forEach((childVirtualDOMElement) => {
|
|
156
|
+
if (visibleNodesForConnection.has(childVirtualDOMElement.nodeId)) {
|
|
157
|
+
removeNodeAndChildrenFromVisibleNodes(childVirtualDOMElement, visibleNodesForConnection);
|
|
158
|
+
diff.removedNodes.push(childVirtualDOMElement.nodeId);
|
|
159
159
|
}
|
|
160
160
|
});
|
|
161
161
|
if (diff.addedNodes.length > 0 || diff.removedNodes.length > 0) {
|
|
@@ -179,9 +179,9 @@ function getNodeIdOfPreviousVisibleSibling(parentVirtualElement, candidateIndex,
|
|
|
179
179
|
}
|
|
180
180
|
return null;
|
|
181
181
|
}
|
|
182
|
-
function shouldShowNodeToConnectionId(
|
|
183
|
-
const visibleToAttr =
|
|
184
|
-
const hiddenFromAttr =
|
|
182
|
+
function shouldShowNodeToConnectionId(virtualDOMElement, connectionId) {
|
|
183
|
+
const visibleToAttr = virtualDOMElement.attributes[visibleToAttrName];
|
|
184
|
+
const hiddenFromAttr = virtualDOMElement.attributes[hiddenFromAttrName];
|
|
185
185
|
const connectionIdString = connectionId.toString();
|
|
186
186
|
if (visibleToAttr !== void 0) {
|
|
187
187
|
const visibleToList = visibleToAttr.split(" ");
|
|
@@ -199,33 +199,33 @@ function shouldShowNodeToConnectionId(virtualDomElement, connectionId) {
|
|
|
199
199
|
}
|
|
200
200
|
return true;
|
|
201
201
|
}
|
|
202
|
-
function describeNodeWithChildrenForConnectionId(
|
|
203
|
-
if (!shouldShowNodeToConnectionId(
|
|
202
|
+
function describeNodeWithChildrenForConnectionId(virtualDOMElement, connectionId, visibleNodesForConnection) {
|
|
203
|
+
if (!shouldShowNodeToConnectionId(virtualDOMElement, connectionId)) {
|
|
204
204
|
return null;
|
|
205
205
|
}
|
|
206
|
-
let emittedTagName =
|
|
206
|
+
let emittedTagName = virtualDOMElement.tag;
|
|
207
207
|
if (emittedTagName === "#document") {
|
|
208
208
|
emittedTagName = "DIV";
|
|
209
209
|
}
|
|
210
210
|
if (emittedTagName === "#text") {
|
|
211
211
|
const textNode = {
|
|
212
212
|
type: "text",
|
|
213
|
-
nodeId:
|
|
214
|
-
text:
|
|
213
|
+
nodeId: virtualDOMElement.nodeId,
|
|
214
|
+
text: virtualDOMElement.textContent || ""
|
|
215
215
|
};
|
|
216
216
|
visibleNodesForConnection.add(textNode.nodeId);
|
|
217
217
|
return textNode;
|
|
218
218
|
} else {
|
|
219
219
|
const node = {
|
|
220
220
|
type: "element",
|
|
221
|
-
nodeId:
|
|
221
|
+
nodeId: virtualDOMElement.nodeId,
|
|
222
222
|
tag: emittedTagName,
|
|
223
|
-
attributes:
|
|
223
|
+
attributes: virtualDOMElement.attributes,
|
|
224
224
|
children: [],
|
|
225
|
-
text:
|
|
225
|
+
text: virtualDOMElement.textContent
|
|
226
226
|
};
|
|
227
227
|
visibleNodesForConnection.add(node.nodeId);
|
|
228
|
-
for (const child of
|
|
228
|
+
for (const child of virtualDOMElement.childNodes) {
|
|
229
229
|
const childNodeDescription = describeNodeWithChildrenForConnectionId(
|
|
230
230
|
child,
|
|
231
231
|
connectionId,
|
|
@@ -238,19 +238,19 @@ function describeNodeWithChildrenForConnectionId(virtualDomElement, connectionId
|
|
|
238
238
|
return node;
|
|
239
239
|
}
|
|
240
240
|
}
|
|
241
|
-
function removeNodeAndChildrenFromVisibleNodes(
|
|
242
|
-
visibleNodesForConnection.delete(
|
|
243
|
-
for (const child of
|
|
241
|
+
function removeNodeAndChildrenFromVisibleNodes(virtualDOMElement, visibleNodesForConnection) {
|
|
242
|
+
visibleNodesForConnection.delete(virtualDOMElement.nodeId);
|
|
243
|
+
for (const child of virtualDOMElement.childNodes) {
|
|
244
244
|
if (!visibleNodesForConnection.has(child.nodeId)) {
|
|
245
245
|
console.error("Inner child of removed element was not visible", child.nodeId);
|
|
246
246
|
}
|
|
247
247
|
removeNodeAndChildrenFromVisibleNodes(child, visibleNodesForConnection);
|
|
248
248
|
}
|
|
249
249
|
}
|
|
250
|
-
function findParentNodeOfNodeId(
|
|
251
|
-
for (const child of
|
|
250
|
+
function findParentNodeOfNodeId(virtualDOMElement, targetNodeId) {
|
|
251
|
+
for (const child of virtualDOMElement.childNodes) {
|
|
252
252
|
if (child.nodeId === targetNodeId) {
|
|
253
|
-
return
|
|
253
|
+
return virtualDOMElement;
|
|
254
254
|
} else {
|
|
255
255
|
const foundParentId = findParentNodeOfNodeId(child, targetNodeId);
|
|
256
256
|
if (foundParentId) {
|
|
@@ -360,7 +360,7 @@ function virtualDOMDiffToVirtualDOMMutationRecord(virtualStructure, domDiff) {
|
|
|
360
360
|
console.error("Unhandled JSON diff:", JSON.stringify(domDiff, null, 2));
|
|
361
361
|
throw new Error("Unhandled diff type");
|
|
362
362
|
}
|
|
363
|
-
function
|
|
363
|
+
function calculateStaticVirtualDOMDiff(originalState, latestState) {
|
|
364
364
|
const jsonPatchDiffs = rfc6902.createPatch(
|
|
365
365
|
originalState,
|
|
366
366
|
latestState,
|
|
@@ -477,16 +477,14 @@ function remapDuplicatedNodeIdsInOperations(virtualDOMDiffStruct, latestState) {
|
|
|
477
477
|
}
|
|
478
478
|
|
|
479
479
|
// src/NetworkedDOM.ts
|
|
480
|
-
var
|
|
481
|
-
var defaultWebsocketSubProtocol =
|
|
480
|
+
var networkedDOMProtocolSubProtocol_v0_1 = "networked-dom-v0.1";
|
|
481
|
+
var defaultWebsocketSubProtocol = networkedDOMProtocolSubProtocol_v0_1;
|
|
482
482
|
var _NetworkedDOM = class {
|
|
483
|
-
constructor(
|
|
483
|
+
constructor(observableDOMFactory, htmlPath, htmlContents, oldInstanceDocumentRoot, onLoad, params = {}, ignoreTextNodes = true, logCallback) {
|
|
484
484
|
// Map from the node ids that the DOM uses internally to the node ids that clients refer to.
|
|
485
485
|
this.internalNodeIdToClientNodeId = /* @__PURE__ */ new Map();
|
|
486
486
|
// Map from the node ids that clients refer to to the node ids that the DOM uses internally.
|
|
487
487
|
this.clientNodeIdToInternalNodeId = /* @__PURE__ */ new Map();
|
|
488
|
-
this.nextNodeId = 1;
|
|
489
|
-
this.ipcWebsockets = /* @__PURE__ */ new Set();
|
|
490
488
|
this.currentConnectionId = 1;
|
|
491
489
|
this.connectionIdToWebSocketContext = /* @__PURE__ */ new Map();
|
|
492
490
|
this.webSocketToConnectionId = /* @__PURE__ */ new Map();
|
|
@@ -502,7 +500,7 @@ var _NetworkedDOM = class {
|
|
|
502
500
|
this.htmlPath = htmlPath;
|
|
503
501
|
this.ignoreTextNodes = ignoreTextNodes;
|
|
504
502
|
this.logCallback = logCallback || this.defaultLogCallback;
|
|
505
|
-
this.
|
|
503
|
+
this.observableDOM = observableDOMFactory(
|
|
506
504
|
{
|
|
507
505
|
htmlPath,
|
|
508
506
|
htmlContents,
|
|
@@ -510,7 +508,8 @@ var _NetworkedDOM = class {
|
|
|
510
508
|
ignoreTextNodes,
|
|
511
509
|
pingIntervalMilliseconds: 5e3
|
|
512
510
|
},
|
|
513
|
-
(message) => {
|
|
511
|
+
(message, observableDOM) => {
|
|
512
|
+
this.observableDOM = observableDOM;
|
|
514
513
|
if (message.documentTime) {
|
|
515
514
|
this.documentEffectiveStartTime = Date.now() - message.documentTime;
|
|
516
515
|
this.latestDocumentTime = message.documentTime;
|
|
@@ -524,13 +523,13 @@ var _NetworkedDOM = class {
|
|
|
524
523
|
this.initialLoad = false;
|
|
525
524
|
let domDiff = null;
|
|
526
525
|
if (oldInstanceDocumentRoot) {
|
|
527
|
-
domDiff =
|
|
526
|
+
domDiff = calculateStaticVirtualDOMDiff(oldInstanceDocumentRoot, clonedSnapshot);
|
|
528
527
|
for (const remapping of domDiff.nodeIdRemappings) {
|
|
529
528
|
this.addRemappedNodeId(remapping.clientFacingNodeId, remapping.internalNodeId);
|
|
530
529
|
}
|
|
531
530
|
}
|
|
532
531
|
this.addAndRemapNodeFromInstance(this.documentRoot, -1);
|
|
533
|
-
onLoad(domDiff);
|
|
532
|
+
onLoad(domDiff, this);
|
|
534
533
|
} else if (message.mutation) {
|
|
535
534
|
if (this.initialLoad) {
|
|
536
535
|
throw new Error("Received mutation before initial load");
|
|
@@ -547,7 +546,7 @@ var _NetworkedDOM = class {
|
|
|
547
546
|
this.sendPings();
|
|
548
547
|
return;
|
|
549
548
|
}
|
|
550
|
-
console.error("Unknown message type from
|
|
549
|
+
console.error("Unknown message type from observableDOM", message);
|
|
551
550
|
}
|
|
552
551
|
}
|
|
553
552
|
);
|
|
@@ -594,7 +593,7 @@ var _NetworkedDOM = class {
|
|
|
594
593
|
webSocketContext.webSocket.send(stringified);
|
|
595
594
|
});
|
|
596
595
|
}
|
|
597
|
-
getInitialSnapshot(connectionId,
|
|
596
|
+
getInitialSnapshot(connectionId, documentVirtualDOMElement) {
|
|
598
597
|
const visibleNodesForConnection = this.visibleNodeIdsByConnectionId.get(connectionId);
|
|
599
598
|
if (!visibleNodesForConnection) {
|
|
600
599
|
const err = new Error(
|
|
@@ -604,7 +603,7 @@ var _NetworkedDOM = class {
|
|
|
604
603
|
throw err;
|
|
605
604
|
}
|
|
606
605
|
const domSnapshot = describeNodeWithChildrenForConnectionId(
|
|
607
|
-
|
|
606
|
+
documentVirtualDOMElement,
|
|
608
607
|
connectionId,
|
|
609
608
|
visibleNodesForConnection
|
|
610
609
|
);
|
|
@@ -656,7 +655,7 @@ var _NetworkedDOM = class {
|
|
|
656
655
|
throw new Error(`could not find parent node of nodeId ${targetNodeId}`);
|
|
657
656
|
}
|
|
658
657
|
diffsByConnectionId.forEach((diffs, connectionId) => {
|
|
659
|
-
const mutationDiff =
|
|
658
|
+
const mutationDiff = diffFromApplicationOfStaticVirtualDOMMutationRecordToConnection(
|
|
660
659
|
mutationRecordLike,
|
|
661
660
|
virtualElementParent,
|
|
662
661
|
connectionId,
|
|
@@ -690,9 +689,9 @@ var _NetworkedDOM = class {
|
|
|
690
689
|
webSocketContext.webSocket.send(serializedDiffs);
|
|
691
690
|
});
|
|
692
691
|
} else {
|
|
693
|
-
const
|
|
694
|
-
if (!
|
|
695
|
-
throw new Error(`
|
|
692
|
+
const documentVirtualDOMElement = this.documentRoot;
|
|
693
|
+
if (!documentVirtualDOMElement) {
|
|
694
|
+
throw new Error(`documentVirtualDOMElement not found in getInitialSnapshot`);
|
|
696
695
|
}
|
|
697
696
|
for (const connectionId of connectionIds) {
|
|
698
697
|
const webSocketContext = this.connectionIdToWebSocketContext.get(connectionId);
|
|
@@ -700,14 +699,14 @@ var _NetworkedDOM = class {
|
|
|
700
699
|
throw new Error(`webSocketContext not found in addExistingWebsockets`);
|
|
701
700
|
}
|
|
702
701
|
const asServerMessages = [
|
|
703
|
-
this.getInitialSnapshot(connectionId,
|
|
702
|
+
this.getInitialSnapshot(connectionId, documentVirtualDOMElement)
|
|
704
703
|
];
|
|
705
704
|
const serializedSnapshotMessage = JSON.stringify(asServerMessages);
|
|
706
705
|
webSocketContext.webSocket.send(serializedSnapshotMessage);
|
|
707
706
|
}
|
|
708
707
|
}
|
|
709
708
|
for (const connectionId of connectionIds) {
|
|
710
|
-
this.
|
|
709
|
+
this.observableDOM.addConnectedUserId(connectionId);
|
|
711
710
|
}
|
|
712
711
|
}
|
|
713
712
|
findParentNodeOfNodeId(targetNodeId) {
|
|
@@ -715,7 +714,7 @@ var _NetworkedDOM = class {
|
|
|
715
714
|
if (parentNodeId === void 0) {
|
|
716
715
|
throw new Error("Parent node ID not found");
|
|
717
716
|
}
|
|
718
|
-
return this.
|
|
717
|
+
return this.getStaticVirtualDOMElementByInternalNodeIdOrThrow(parentNodeId);
|
|
719
718
|
}
|
|
720
719
|
registerWebsocket(webSocket, existingConnectionId = null) {
|
|
721
720
|
let connectionId;
|
|
@@ -727,8 +726,8 @@ var _NetworkedDOM = class {
|
|
|
727
726
|
}
|
|
728
727
|
const webSocketContext = {
|
|
729
728
|
webSocket,
|
|
730
|
-
messageListener: (
|
|
731
|
-
const string = String(
|
|
729
|
+
messageListener: (messageEvent) => {
|
|
730
|
+
const string = String(messageEvent.data);
|
|
732
731
|
let parsed;
|
|
733
732
|
try {
|
|
734
733
|
parsed = JSON.parse(string);
|
|
@@ -749,13 +748,6 @@ var _NetworkedDOM = class {
|
|
|
749
748
|
webSocket.addEventListener("message", webSocketContext.messageListener);
|
|
750
749
|
return { connectionId };
|
|
751
750
|
}
|
|
752
|
-
addIPCWebSocket(webSocket) {
|
|
753
|
-
this.ipcWebsockets.add(webSocket);
|
|
754
|
-
webSocket.addEventListener("close", () => {
|
|
755
|
-
this.ipcWebsockets.delete(webSocket);
|
|
756
|
-
});
|
|
757
|
-
this.observableDom.addIPCWebsocket(webSocket);
|
|
758
|
-
}
|
|
759
751
|
static handleWebsocketSubprotocol(protocols) {
|
|
760
752
|
const protocolsSet = new Set(protocols);
|
|
761
753
|
for (const protocol of _NetworkedDOM.SupportedWebsocketSubProtocolsPreferenceOrder) {
|
|
@@ -797,23 +789,23 @@ var _NetworkedDOM = class {
|
|
|
797
789
|
webSocket.send(JSON.stringify(warningMessage));
|
|
798
790
|
}
|
|
799
791
|
const { connectionId } = this.registerWebsocket(webSocket);
|
|
800
|
-
const
|
|
801
|
-
if (!
|
|
802
|
-
throw new Error(`
|
|
792
|
+
const documentVirtualDOMElement = this.documentRoot;
|
|
793
|
+
if (!documentVirtualDOMElement) {
|
|
794
|
+
throw new Error(`documentVirtualDOMElement not found in getInitialSnapshot`);
|
|
803
795
|
}
|
|
804
796
|
const asServerMessages = [
|
|
805
|
-
this.getInitialSnapshot(connectionId,
|
|
797
|
+
this.getInitialSnapshot(connectionId, documentVirtualDOMElement)
|
|
806
798
|
];
|
|
807
799
|
const serializedSnapshotMessage = JSON.stringify(asServerMessages);
|
|
808
800
|
webSocket.send(serializedSnapshotMessage);
|
|
809
|
-
this.
|
|
801
|
+
this.observableDOM.addConnectedUserId(connectionId);
|
|
810
802
|
}
|
|
811
803
|
removeWebSocket(webSocket) {
|
|
812
804
|
const connectionId = this.webSocketToConnectionId.get(webSocket);
|
|
813
805
|
if (!connectionId) {
|
|
814
806
|
return;
|
|
815
807
|
}
|
|
816
|
-
this.
|
|
808
|
+
this.observableDOM.removeConnectedUserId(connectionId);
|
|
817
809
|
const webSocketContext = this.connectionIdToWebSocketContext.get(connectionId);
|
|
818
810
|
if (!webSocketContext) {
|
|
819
811
|
throw new Error("Missing context for websocket");
|
|
@@ -826,9 +818,9 @@ var _NetworkedDOM = class {
|
|
|
826
818
|
dispose() {
|
|
827
819
|
this.disposed = true;
|
|
828
820
|
for (const [, connectionId] of this.webSocketToConnectionId) {
|
|
829
|
-
this.
|
|
821
|
+
this.observableDOM.removeConnectedUserId(connectionId);
|
|
830
822
|
}
|
|
831
|
-
this.
|
|
823
|
+
this.observableDOM.dispose();
|
|
832
824
|
for (const [webSocket, connectionId] of this.webSocketToConnectionId) {
|
|
833
825
|
const webSocketContext = this.connectionIdToWebSocketContext.get(connectionId);
|
|
834
826
|
if (!webSocketContext) {
|
|
@@ -839,17 +831,14 @@ var _NetworkedDOM = class {
|
|
|
839
831
|
this.visibleNodeIdsByConnectionId.delete(connectionId);
|
|
840
832
|
this.webSocketToConnectionId.delete(webSocket);
|
|
841
833
|
}
|
|
842
|
-
for (const ipcWebsocket of this.ipcWebsockets) {
|
|
843
|
-
ipcWebsocket.close();
|
|
844
|
-
}
|
|
845
834
|
}
|
|
846
835
|
processModification(mutationRecord) {
|
|
847
|
-
const
|
|
848
|
-
if (!
|
|
836
|
+
const documentVirtualDOMElement = this.documentRoot;
|
|
837
|
+
if (!documentVirtualDOMElement) {
|
|
849
838
|
throw new Error(`document not created in processModification`);
|
|
850
839
|
}
|
|
851
840
|
for (const [, visibleNodesForConnection] of this.visibleNodeIdsByConnectionId) {
|
|
852
|
-
visibleNodesForConnection.add(
|
|
841
|
+
visibleNodesForConnection.add(documentVirtualDOMElement.nodeId);
|
|
853
842
|
}
|
|
854
843
|
const diffsByConnectionId = new Map(
|
|
855
844
|
Array.from(this.connectionIdToWebSocketContext.keys()).map((connectionId) => [
|
|
@@ -863,7 +852,7 @@ var _NetworkedDOM = class {
|
|
|
863
852
|
console.error("parentNode not found for attribute mutationRecord", mutationRecord);
|
|
864
853
|
console.error("this.documentRoot", JSON.stringify(this.documentRoot, null, 2));
|
|
865
854
|
}
|
|
866
|
-
const diff =
|
|
855
|
+
const diff = diffFromApplicationOfStaticVirtualDOMMutationRecordToConnection(
|
|
867
856
|
mutationRecord,
|
|
868
857
|
parentNode,
|
|
869
858
|
connectionId,
|
|
@@ -887,21 +876,21 @@ var _NetworkedDOM = class {
|
|
|
887
876
|
});
|
|
888
877
|
}
|
|
889
878
|
removeKnownNodesInMutation(mutation) {
|
|
890
|
-
const
|
|
879
|
+
const virtualDOMElement = mutation.target;
|
|
891
880
|
if (mutation.type === "childList") {
|
|
892
|
-
mutation.removedNodes.forEach((
|
|
893
|
-
this.
|
|
894
|
-
const index =
|
|
895
|
-
|
|
881
|
+
mutation.removedNodes.forEach((childDOMElement) => {
|
|
882
|
+
this.removeVirtualDOMElement(childDOMElement);
|
|
883
|
+
const index = virtualDOMElement.childNodes.indexOf(childDOMElement);
|
|
884
|
+
virtualDOMElement.childNodes.splice(index, 1);
|
|
896
885
|
});
|
|
897
886
|
return;
|
|
898
887
|
}
|
|
899
888
|
}
|
|
900
|
-
|
|
901
|
-
this.nodeIdToNode.delete(
|
|
902
|
-
this.nodeIdToParentNodeId.delete(
|
|
903
|
-
for (const child of
|
|
904
|
-
this.
|
|
889
|
+
removeVirtualDOMElement(virtualDOMElement) {
|
|
890
|
+
this.nodeIdToNode.delete(virtualDOMElement.nodeId);
|
|
891
|
+
this.nodeIdToParentNodeId.delete(virtualDOMElement.nodeId);
|
|
892
|
+
for (const child of virtualDOMElement.childNodes) {
|
|
893
|
+
this.removeVirtualDOMElement(child);
|
|
905
894
|
}
|
|
906
895
|
}
|
|
907
896
|
static IsPongMessage(message) {
|
|
@@ -930,9 +919,9 @@ var _NetworkedDOM = class {
|
|
|
930
919
|
if (remappedNode) {
|
|
931
920
|
remoteEvent.nodeId = remappedNode;
|
|
932
921
|
}
|
|
933
|
-
this.
|
|
922
|
+
this.observableDOM.dispatchRemoteEventFromConnectionId(connectionId, remoteEvent);
|
|
934
923
|
}
|
|
935
|
-
|
|
924
|
+
getStaticVirtualDOMElementByInternalNodeIdOrThrow(internalNodeId) {
|
|
936
925
|
const remappedId = this.internalNodeIdToClientNodeId.get(internalNodeId);
|
|
937
926
|
if (remappedId !== void 0) {
|
|
938
927
|
const node2 = this.nodeIdToNode.get(remappedId);
|
|
@@ -948,7 +937,7 @@ var _NetworkedDOM = class {
|
|
|
948
937
|
return node;
|
|
949
938
|
}
|
|
950
939
|
addKnownNodesInMutation(mutation) {
|
|
951
|
-
const target = this.
|
|
940
|
+
const target = this.getStaticVirtualDOMElementByInternalNodeIdOrThrow(mutation.targetId);
|
|
952
941
|
if (mutation.attribute) {
|
|
953
942
|
if (mutation.attribute.value !== null) {
|
|
954
943
|
target.attributes[mutation.attribute.attributeName] = mutation.attribute.value;
|
|
@@ -956,7 +945,7 @@ var _NetworkedDOM = class {
|
|
|
956
945
|
delete target.attributes[mutation.attribute.attributeName];
|
|
957
946
|
}
|
|
958
947
|
}
|
|
959
|
-
const previousSibling = mutation.previousSiblingId ? this.
|
|
948
|
+
const previousSibling = mutation.previousSiblingId ? this.getStaticVirtualDOMElementByInternalNodeIdOrThrow(mutation.previousSiblingId) : null;
|
|
960
949
|
if (mutation.type === "childList") {
|
|
961
950
|
let index = 0;
|
|
962
951
|
if (previousSibling) {
|
|
@@ -966,10 +955,10 @@ var _NetworkedDOM = class {
|
|
|
966
955
|
}
|
|
967
956
|
index += 1;
|
|
968
957
|
}
|
|
969
|
-
mutation.addedNodes.forEach((
|
|
970
|
-
this.addAndRemapNodeFromInstance(
|
|
971
|
-
if (target.childNodes.indexOf(
|
|
972
|
-
target.childNodes.splice(index, 0,
|
|
958
|
+
mutation.addedNodes.forEach((childVirtualDOMElement) => {
|
|
959
|
+
this.addAndRemapNodeFromInstance(childVirtualDOMElement, target.nodeId);
|
|
960
|
+
if (target.childNodes.indexOf(childVirtualDOMElement) === -1) {
|
|
961
|
+
target.childNodes.splice(index, 0, childVirtualDOMElement);
|
|
973
962
|
index++;
|
|
974
963
|
}
|
|
975
964
|
});
|
|
@@ -988,9 +977,9 @@ var _NetworkedDOM = class {
|
|
|
988
977
|
target,
|
|
989
978
|
addedNodes: mutation.addedNodes,
|
|
990
979
|
removedNodes: mutation.removedNodeIds.map((nodeId) => {
|
|
991
|
-
return this.
|
|
980
|
+
return this.getStaticVirtualDOMElementByInternalNodeIdOrThrow(nodeId);
|
|
992
981
|
}),
|
|
993
|
-
previousSibling: mutation.previousSiblingId ? this.
|
|
982
|
+
previousSibling: mutation.previousSiblingId ? this.getStaticVirtualDOMElementByInternalNodeIdOrThrow(mutation.previousSiblingId) : null,
|
|
994
983
|
attributeName: mutation.attribute ? mutation.attribute.attributeName : null
|
|
995
984
|
};
|
|
996
985
|
return record;
|
|
@@ -1027,7 +1016,7 @@ var _NetworkedDOM = class {
|
|
|
1027
1016
|
var NetworkedDOM = _NetworkedDOM;
|
|
1028
1017
|
// First to last in order of preference
|
|
1029
1018
|
NetworkedDOM.SupportedWebsocketSubProtocolsPreferenceOrder = [
|
|
1030
|
-
|
|
1019
|
+
networkedDOMProtocolSubProtocol_v0_1
|
|
1031
1020
|
];
|
|
1032
1021
|
|
|
1033
1022
|
// src/EditableNetworkedDOM.ts
|
|
@@ -1063,12 +1052,12 @@ var EditableNetworkedDOM = class {
|
|
|
1063
1052
|
this.htmlPath,
|
|
1064
1053
|
htmlContents,
|
|
1065
1054
|
oldInstanceRoot,
|
|
1066
|
-
(domDiff) => {
|
|
1055
|
+
(domDiff, networkedDOM2) => {
|
|
1067
1056
|
didLoad = true;
|
|
1068
1057
|
if (this.loadedState) {
|
|
1069
1058
|
this.loadedState.loaded = true;
|
|
1070
1059
|
}
|
|
1071
|
-
|
|
1060
|
+
networkedDOM2.addExistingWebsockets(
|
|
1072
1061
|
Array.from(this.websockets),
|
|
1073
1062
|
existingWebsocketMap,
|
|
1074
1063
|
domDiff
|
|
@@ -1113,21 +1102,12 @@ var EditableNetworkedDOM = class {
|
|
|
1113
1102
|
this.loadedState.networkedDOM.removeWebSocket(webSocket);
|
|
1114
1103
|
}
|
|
1115
1104
|
}
|
|
1116
|
-
addIPCWebSocket(webSocket) {
|
|
1117
|
-
if (this.loadedState && this.loadedState.loaded) {
|
|
1118
|
-
this.loadedState.networkedDOM.addIPCWebSocket(webSocket);
|
|
1119
|
-
} else {
|
|
1120
|
-
console.error("Dom instance not loaded/ready to accept IPC websocket");
|
|
1121
|
-
webSocket.close();
|
|
1122
|
-
return;
|
|
1123
|
-
}
|
|
1124
|
-
}
|
|
1125
1105
|
};
|
|
1126
1106
|
// Annotate the CommonJS export names for ESM import in node:
|
|
1127
1107
|
0 && (module.exports = {
|
|
1128
1108
|
EditableNetworkedDOM,
|
|
1129
1109
|
NetworkedDOM,
|
|
1130
1110
|
defaultWebsocketSubProtocol,
|
|
1131
|
-
|
|
1111
|
+
networkedDOMProtocolSubProtocol_v0_1
|
|
1132
1112
|
});
|
|
1133
1113
|
//# sourceMappingURL=index.js.map
|