@mml-io/networked-dom-web-client 0.20.0 → 0.21.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 CHANGED
@@ -292,6 +292,31 @@ function decodeNodeDescription(buffer) {
292
292
  return node;
293
293
  }
294
294
  var networkedDOMProtocolSubProtocol_v0_2 = "networked-dom-v0.2";
295
+ var networkedDOMProtocolSubProtocol_v0_2_1 = "networked-dom-v0.2.1";
296
+ var networkedDOMProtocolSubProtocol_v0_2_SubVersionsList = [
297
+ networkedDOMProtocolSubProtocol_v0_2_1,
298
+ networkedDOMProtocolSubProtocol_v0_2
299
+ ];
300
+ var protocolSubVersionMap = {
301
+ [networkedDOMProtocolSubProtocol_v0_2]: 0,
302
+ [networkedDOMProtocolSubProtocol_v0_2_1]: 1
303
+ };
304
+ function getNetworkedDOMProtocolSubProtocol_v0_2Subversion(protocol) {
305
+ return protocolSubVersionMap[protocol] ?? null;
306
+ }
307
+ function getNetworkedDOMProtocolSubProtocol_v0_2SubversionOrThrow(protocol) {
308
+ const subversion = getNetworkedDOMProtocolSubProtocol_v0_2Subversion(protocol);
309
+ if (subversion === null) {
310
+ throw new Error(`Unrecognized networked-dom-v0.2 protocol subversion: ${protocol}`);
311
+ }
312
+ return subversion;
313
+ }
314
+ function isNetworkedDOMProtocolSubProtocol_v0_2(protocol) {
315
+ return networkedDOMProtocolSubProtocol_v0_2_SubVersionsList.includes(protocol);
316
+ }
317
+ function protocolSubversionHasConnectionTokens(protocolSubversion) {
318
+ return protocolSubversion >= 1;
319
+ }
295
320
  var SnapshotMessageType = 1;
296
321
  var BatchStartMessageType = 2;
297
322
  var DocumentTimeMessageType = 3;
@@ -309,13 +334,28 @@ var ConnectUsersMessageType = 14;
309
334
  var DisconnectUsersMessageType = 15;
310
335
  var EventMessageType = 16;
311
336
  var PongMessageType = 17;
312
- function encodeConnectUsers(connectUsersMessage, writer) {
337
+ function encodeConnectUsers(connectUsersMessage, writer, protocolSubversion) {
313
338
  const connectionIdsLength = connectUsersMessage.connectionIds.length;
314
339
  writer.writeUint8(ConnectUsersMessageType);
315
340
  writer.writeUVarint(connectionIdsLength);
316
341
  for (let i = 0; i < connectionIdsLength; i++) {
317
342
  writer.writeUVarint(connectUsersMessage.connectionIds[i]);
318
343
  }
344
+ if (protocolSubversionHasConnectionTokens(protocolSubversion)) {
345
+ if (connectUsersMessage.connectionTokens.length !== connectionIdsLength) {
346
+ throw new Error(
347
+ `connectionTokens length (${connectUsersMessage.connectionTokens.length}) does not match connectionIds length (${connectionIdsLength})`
348
+ );
349
+ }
350
+ for (let i = 0; i < connectionIdsLength; i++) {
351
+ const token = connectUsersMessage.connectionTokens[i];
352
+ if (token === null || token === void 0) {
353
+ writer.writeUVarint(0);
354
+ } else {
355
+ writer.writeLengthPrefixedString(token);
356
+ }
357
+ }
358
+ }
319
359
  }
320
360
  function encodeDisconnectUsers(disconnectUsersMessage, writer) {
321
361
  const connectionIdsLength = disconnectUsersMessage.connectionIds.length;
@@ -513,11 +553,11 @@ function decodeServerMessages(buffer) {
513
553
  }
514
554
  return messages;
515
555
  }
516
- function encodeClientMessage(message, writer) {
556
+ function encodeClientMessage(message, writer, protocolSubversion) {
517
557
  const type = message.type;
518
558
  switch (type) {
519
559
  case "connectUsers":
520
- return encodeConnectUsers(message, writer);
560
+ return encodeConnectUsers(message, writer, protocolSubversion);
521
561
  case "disconnectUsers":
522
562
  return encodeDisconnectUsers(message, writer);
523
563
  case "event":
@@ -591,7 +631,7 @@ var DOMSanitizer = class _DOMSanitizer {
591
631
  return c >= "0" && c <= "9";
592
632
  }
593
633
  static IsASCIIAlpha(c) {
594
- return c >= "a" && c <= "z";
634
+ return c >= "a" && c <= "z" || c >= "A" && c <= "Z";
595
635
  }
596
636
  static IsValidAttributeName(characters) {
597
637
  const c = characters[0];
@@ -614,6 +654,172 @@ var DOMSanitizer = class _DOMSanitizer {
614
654
  return !attribute.startsWith("on");
615
655
  }
616
656
  };
657
+ var ALWAYS_DISALLOWED_TAGS = /* @__PURE__ */ new Set(["foreignobject", "iframe", "script"]);
658
+ var SVG_TAG_NAMES_ADJUSTMENT_MAP = new Map(
659
+ [
660
+ "svg",
661
+ "defs",
662
+ "g",
663
+ "text",
664
+ "filter",
665
+ "stop",
666
+ "path",
667
+ "rect",
668
+ "line",
669
+ "circle",
670
+ "animate",
671
+ "altGlyph",
672
+ "altGlyphDef",
673
+ "altGlyphItem",
674
+ "animateColor",
675
+ "animateMotion",
676
+ "animateTransform",
677
+ "clipPath",
678
+ "feBlend",
679
+ "feDropShadow",
680
+ "feColorMatrix",
681
+ "feComponentTransfer",
682
+ "feComposite",
683
+ "feConvolveMatrix",
684
+ "feDiffuseLighting",
685
+ "feDisplacementMap",
686
+ "feDistantLight",
687
+ "feFlood",
688
+ "feFuncA",
689
+ "feFuncB",
690
+ "feFuncG",
691
+ "feFuncR",
692
+ "feGaussianBlur",
693
+ "feImage",
694
+ "feMerge",
695
+ "feMergeNode",
696
+ "feMorphology",
697
+ "feOffset",
698
+ "fePointLight",
699
+ "feSpecularLighting",
700
+ "feSpotLight",
701
+ "feTile",
702
+ "feTurbulence",
703
+ "glyphRef",
704
+ "linearGradient",
705
+ "radialGradient",
706
+ "textPath"
707
+ // `foreignObject` is explicitly disallowed because it allows injecting arbitrary HTML
708
+ // "foreignObject",
709
+ ].map((tn) => [tn.toLowerCase(), tn])
710
+ );
711
+ var SVG_ATTRS_ADJUSTMENT_MAP = new Map(
712
+ [
713
+ "attributeName",
714
+ "attributeType",
715
+ "baseFrequency",
716
+ "baseProfile",
717
+ "calcMode",
718
+ "clipPathUnits",
719
+ "diffuseConstant",
720
+ "edgeMode",
721
+ "filterUnits",
722
+ "glyphRef",
723
+ "gradientTransform",
724
+ "gradientUnits",
725
+ "kernelMatrix",
726
+ "kernelUnitLength",
727
+ "keyPoints",
728
+ "keySplines",
729
+ "keyTimes",
730
+ "lengthAdjust",
731
+ "limitingConeAngle",
732
+ "markerHeight",
733
+ "markerUnits",
734
+ "markerWidth",
735
+ "maskContentUnits",
736
+ "maskUnits",
737
+ "numOctaves",
738
+ "pathLength",
739
+ "patternContentUnits",
740
+ "patternTransform",
741
+ "patternUnits",
742
+ "pointsAtX",
743
+ "pointsAtY",
744
+ "pointsAtZ",
745
+ "preserveAlpha",
746
+ "preserveAspectRatio",
747
+ "primitiveUnits",
748
+ "refX",
749
+ "refY",
750
+ "repeatCount",
751
+ "repeatDur",
752
+ "requiredExtensions",
753
+ "requiredFeatures",
754
+ "specularConstant",
755
+ "specularExponent",
756
+ "spreadMethod",
757
+ "startOffset",
758
+ "stdDeviation",
759
+ "stitchTiles",
760
+ "surfaceScale",
761
+ "systemLanguage",
762
+ "tableValues",
763
+ "targetX",
764
+ "targetY",
765
+ "textLength",
766
+ "viewBox",
767
+ "viewTarget",
768
+ "xChannelSelector",
769
+ "yChannelSelector",
770
+ "zoomAndPan"
771
+ ].map((attr) => [attr.toLowerCase(), attr])
772
+ );
773
+ function remapAttributeName(attrName) {
774
+ const remapped = SVG_ATTRS_ADJUSTMENT_MAP.get(attrName.toLowerCase());
775
+ if (remapped) {
776
+ return remapped;
777
+ }
778
+ return attrName;
779
+ }
780
+ function createElementWithSVGSupport(tag, options = {}) {
781
+ let filteredTag = tag.toLowerCase();
782
+ if (ALWAYS_DISALLOWED_TAGS.has(filteredTag.toLowerCase())) {
783
+ console.error("Disallowing tag", filteredTag);
784
+ filteredTag = options.replacementTagPrefix ? options.replacementTagPrefix + tag : `x-${tag}`;
785
+ }
786
+ let svgTagMapping;
787
+ if (options.allowSVGElements) {
788
+ svgTagMapping = SVG_TAG_NAMES_ADJUSTMENT_MAP.get(filteredTag);
789
+ }
790
+ if (svgTagMapping) {
791
+ filteredTag = svgTagMapping;
792
+ const xmlns = "http://www.w3.org/2000/svg";
793
+ return document.createElementNS(xmlns, filteredTag);
794
+ } else {
795
+ if (options.tagPrefix) {
796
+ if (!tag.toLowerCase().startsWith(options.tagPrefix.toLowerCase())) {
797
+ filteredTag = options.replacementTagPrefix ? options.replacementTagPrefix + tag : `x-${tag}`;
798
+ }
799
+ }
800
+ return document.createElement(filteredTag);
801
+ }
802
+ }
803
+ function setElementAttribute(element, key, value) {
804
+ if (DOMSanitizer.shouldAcceptAttribute(key)) {
805
+ const remappedKey = remapAttributeName(key);
806
+ element.setAttribute(remappedKey, value);
807
+ }
808
+ }
809
+ function getChildrenTarget(parent) {
810
+ let targetForChildren = parent;
811
+ if (parent.getPortalElement) {
812
+ targetForChildren = parent.getPortalElement();
813
+ }
814
+ return targetForChildren;
815
+ }
816
+ function getRemovalTarget(parent) {
817
+ let targetForRemoval = parent;
818
+ if (parent.getPortalElement) {
819
+ targetForRemoval = parent.getPortalElement();
820
+ }
821
+ return targetForRemoval;
822
+ }
617
823
  var NetworkedDOMWebsocketV01Adapter = class {
618
824
  constructor(websocket, parentElement, connectedCallback, timeCallback, options = {}) {
619
825
  this.websocket = websocket;
@@ -732,6 +938,7 @@ var NetworkedDOMWebsocketV01Adapter = class {
732
938
  if (!isHTMLElement(parent, this.parentElement)) {
733
939
  throw new Error("Parent is not an HTMLElement (that supports children)");
734
940
  }
941
+ const targetForChildren = getChildrenTarget(parent);
735
942
  let nextElement = null;
736
943
  let previousElement = null;
737
944
  if (previousNodeId) {
@@ -753,12 +960,12 @@ var NetworkedDOMWebsocketV01Adapter = class {
753
960
  if (nextElement) {
754
961
  const docFrag = new DocumentFragment();
755
962
  docFrag.append(...elementsToAdd);
756
- parent.insertBefore(docFrag, nextElement);
963
+ targetForChildren.insertBefore(docFrag, nextElement);
757
964
  } else {
758
- parent.append(...elementsToAdd);
965
+ targetForChildren.append(...elementsToAdd);
759
966
  }
760
967
  } else {
761
- parent.prepend(...elementsToAdd);
968
+ targetForChildren.prepend(...elementsToAdd);
762
969
  }
763
970
  }
764
971
  for (const removedNode of removedNodes) {
@@ -768,15 +975,20 @@ var NetworkedDOMWebsocketV01Adapter = class {
768
975
  }
769
976
  this.elementToId.delete(childElement);
770
977
  this.idToElement.delete(removedNode);
771
- parent.removeChild(childElement);
978
+ const targetForRemoval = getRemovalTarget(parent);
979
+ targetForRemoval.removeChild(childElement);
772
980
  if (isHTMLElement(childElement, this.parentElement)) {
773
981
  this.removeChildElementIds(childElement);
774
982
  }
775
983
  }
776
984
  }
777
985
  removeChildElementIds(parent) {
778
- for (let i = 0; i < parent.children.length; i++) {
779
- const child = parent.children[i];
986
+ const portal = getChildrenTarget(parent);
987
+ if (portal !== parent) {
988
+ this.removeChildElementIds(portal);
989
+ }
990
+ for (let i = 0; i < parent.childNodes.length; i++) {
991
+ const child = parent.childNodes[i];
780
992
  const childId = this.elementToId.get(child);
781
993
  if (!childId) {
782
994
  console.error("Inner child of removed element had no id", child);
@@ -816,9 +1028,7 @@ var NetworkedDOMWebsocketV01Adapter = class {
816
1028
  if (newValue === null) {
817
1029
  element.removeAttribute(attribute);
818
1030
  } else {
819
- if (DOMSanitizer.shouldAcceptAttribute(attribute)) {
820
- element.setAttribute(attribute, newValue);
821
- }
1031
+ setElementAttribute(element, attribute, newValue);
822
1032
  }
823
1033
  } else {
824
1034
  console.error("Element is not an HTMLElement and cannot support attributes", element);
@@ -857,13 +1067,7 @@ var NetworkedDOMWebsocketV01Adapter = class {
857
1067
  }
858
1068
  let element;
859
1069
  try {
860
- let filteredTag = tag;
861
- if (this.options.tagPrefix) {
862
- if (!tag.toLowerCase().startsWith(this.options.tagPrefix.toLowerCase())) {
863
- filteredTag = this.options.replacementTagPrefix ? this.options.replacementTagPrefix + tag : `x-${tag}`;
864
- }
865
- }
866
- element = document.createElement(filteredTag);
1070
+ element = createElementWithSVGSupport(tag, this.options);
867
1071
  } catch (e) {
868
1072
  console.error(`Error creating element: (${tag})`, e);
869
1073
  element = document.createElement("x-div");
@@ -871,10 +1075,8 @@ var NetworkedDOMWebsocketV01Adapter = class {
871
1075
  this.idToElement.set(nodeId, element);
872
1076
  this.elementToId.set(element, nodeId);
873
1077
  for (const key in attributes) {
874
- if (DOMSanitizer.shouldAcceptAttribute(key)) {
875
- const value = attributes[key];
876
- element.setAttribute(key, value);
877
- }
1078
+ const value = attributes[key];
1079
+ setElementAttribute(element, key, value);
878
1080
  }
879
1081
  if (children) {
880
1082
  for (const child of children) {
@@ -903,7 +1105,14 @@ var NetworkedDOMWebsocketV02Adapter = class {
903
1105
  this.batchMode = false;
904
1106
  this.batchMessages = [];
905
1107
  this.websocket.binaryType = "arraybuffer";
906
- this.send({ type: "connectUsers", connectionIds: [connectionId] });
1108
+ this.protocolSubversion = getNetworkedDOMProtocolSubProtocol_v0_2SubversionOrThrow(
1109
+ websocket.protocol
1110
+ );
1111
+ this.send({
1112
+ type: "connectUsers",
1113
+ connectionIds: [connectionId],
1114
+ connectionTokens: [this.options.connectionToken ?? null]
1115
+ });
907
1116
  }
908
1117
  handleEvent(element, event) {
909
1118
  const nodeId = this.elementToId.get(element);
@@ -927,7 +1136,7 @@ var NetworkedDOMWebsocketV02Adapter = class {
927
1136
  }
928
1137
  send(message) {
929
1138
  const writer = new BufferWriter(256);
930
- encodeClientMessage(message, writer);
1139
+ encodeClientMessage(message, writer, this.protocolSubversion);
931
1140
  this.websocket.send(writer.getBuffer());
932
1141
  }
933
1142
  clearContents() {
@@ -1068,6 +1277,7 @@ var NetworkedDOMWebsocketV02Adapter = class {
1068
1277
  if (!isHTMLElement(parent, this.parentElement)) {
1069
1278
  throw new Error("Parent is not an HTMLElement (that supports children)");
1070
1279
  }
1280
+ const targetForChildren = getChildrenTarget(parent);
1071
1281
  let nextElement = null;
1072
1282
  let previousElement = null;
1073
1283
  if (previousNodeId) {
@@ -1089,12 +1299,12 @@ var NetworkedDOMWebsocketV02Adapter = class {
1089
1299
  if (nextElement) {
1090
1300
  const docFrag = new DocumentFragment();
1091
1301
  docFrag.append(...elementsToAdd);
1092
- parent.insertBefore(docFrag, nextElement);
1302
+ targetForChildren.insertBefore(docFrag, nextElement);
1093
1303
  } else {
1094
- parent.append(...elementsToAdd);
1304
+ targetForChildren.append(...elementsToAdd);
1095
1305
  }
1096
1306
  } else {
1097
- parent.prepend(...elementsToAdd);
1307
+ targetForChildren.prepend(...elementsToAdd);
1098
1308
  }
1099
1309
  }
1100
1310
  }
@@ -1122,15 +1332,20 @@ var NetworkedDOMWebsocketV02Adapter = class {
1122
1332
  this.elementToId.delete(childElement);
1123
1333
  this.idToElement.delete(removedNode);
1124
1334
  this.hiddenPlaceholderElements.delete(removedNode);
1125
- parent.removeChild(childElement);
1335
+ const targetForRemoval = getRemovalTarget(parent);
1336
+ targetForRemoval.removeChild(childElement);
1126
1337
  if (isHTMLElement(childElement, this.parentElement)) {
1127
1338
  this.removeChildElementIds(childElement);
1128
1339
  }
1129
1340
  }
1130
1341
  }
1131
1342
  removeChildElementIds(parent) {
1132
- for (let i = 0; i < parent.children.length; i++) {
1133
- const child = parent.children[i];
1343
+ const portal = getChildrenTarget(parent);
1344
+ if (portal !== parent) {
1345
+ this.removeChildElementIds(portal);
1346
+ }
1347
+ for (let i = 0; i < parent.childNodes.length; i++) {
1348
+ const child = parent.childNodes[i];
1134
1349
  const childId = this.elementToId.get(child);
1135
1350
  if (!childId) {
1136
1351
  console.error("Inner child of removed element had no id", child);
@@ -1182,9 +1397,7 @@ var NetworkedDOMWebsocketV02Adapter = class {
1182
1397
  if (newValue === null) {
1183
1398
  element.removeAttribute(key);
1184
1399
  } else {
1185
- if (DOMSanitizer.shouldAcceptAttribute(key)) {
1186
- element.setAttribute(key, newValue);
1187
- }
1400
+ setElementAttribute(element, key, newValue);
1188
1401
  }
1189
1402
  }
1190
1403
  } else {
@@ -1221,22 +1434,14 @@ var NetworkedDOMWebsocketV02Adapter = class {
1221
1434
  }
1222
1435
  let element;
1223
1436
  try {
1224
- let filteredTag = tag;
1225
- if (this.options.tagPrefix) {
1226
- if (!tag.toLowerCase().startsWith(this.options.tagPrefix.toLowerCase())) {
1227
- filteredTag = this.options.replacementTagPrefix ? this.options.replacementTagPrefix + tag : `x-${tag}`;
1228
- }
1229
- }
1230
- element = document.createElement(filteredTag);
1437
+ element = createElementWithSVGSupport(tag, this.options);
1231
1438
  } catch (e) {
1232
1439
  console.error(`Error creating element: (${tag})`, e);
1233
1440
  element = document.createElement("x-div");
1234
1441
  }
1235
1442
  for (const [key, value] of attributes) {
1236
1443
  if (value !== null) {
1237
- if (DOMSanitizer.shouldAcceptAttribute(key)) {
1238
- element.setAttribute(key, value);
1239
- }
1444
+ setElementAttribute(element, key, value);
1240
1445
  }
1241
1446
  }
1242
1447
  if (children) {
@@ -1292,7 +1497,7 @@ var NetworkedDOMWebsocket = class {
1292
1497
  }
1293
1498
  static createWebSocket(url) {
1294
1499
  return new WebSocket(url, [
1295
- networkedDOMProtocolSubProtocol_v0_2,
1500
+ ...networkedDOMProtocolSubProtocol_v0_2_SubVersionsList,
1296
1501
  networkedDOMProtocolSubProtocol_v0_1
1297
1502
  ]);
1298
1503
  }
@@ -1315,7 +1520,7 @@ var NetworkedDOMWebsocket = class {
1315
1520
  websocket.addEventListener("open", () => {
1316
1521
  clearTimeout(timeoutId);
1317
1522
  this.websocket = websocket;
1318
- const isV02 = websocket.protocol === networkedDOMProtocolSubProtocol_v0_2;
1523
+ const isV02 = isNetworkedDOMProtocolSubProtocol_v0_2(websocket.protocol);
1319
1524
  let websocketAdapter;
1320
1525
  if (isV02) {
1321
1526
  websocketAdapter = new NetworkedDOMWebsocketV02Adapter(
@@ -1447,7 +1652,7 @@ var NetworkedDOMWebsocket = class {
1447
1652
  }
1448
1653
  };
1449
1654
  function isHTMLElement(node, rootNode) {
1450
- if (node instanceof HTMLElement) {
1655
+ if (node instanceof HTMLElement || node instanceof Element) {
1451
1656
  return true;
1452
1657
  }
1453
1658
  if (!rootNode.ownerDocument.defaultView) {
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
- "sources": ["../../networked-dom-protocol/src/networked-dom-v0.1/constants.ts", "../../networked-dom-protocol/src/networked-dom-v0.2/BufferReader.ts", "../../networked-dom-protocol/src/networked-dom-v0.2/BufferWriter.ts", "../../networked-dom-protocol/src/networked-dom-v0.2/common-structs/attributes.ts", "../../networked-dom-protocol/src/networked-dom-v0.2/common-structs/nodeDescription.ts", "../../networked-dom-protocol/src/networked-dom-v0.2/constants.ts", "../../networked-dom-protocol/src/networked-dom-v0.2/messageTypes.ts", "../../networked-dom-protocol/src/networked-dom-v0.2/messages/from-client/connectUsers.ts", "../../networked-dom-protocol/src/networked-dom-v0.2/messages/from-client/disconnectUsers.ts", "../../networked-dom-protocol/src/networked-dom-v0.2/messages/from-client/event.ts", "../../networked-dom-protocol/src/networked-dom-v0.2/messages/from-client/pong.ts", "../../networked-dom-protocol/src/networked-dom-v0.2/decodeClientMessages.ts", "../../networked-dom-protocol/src/networked-dom-v0.2/messages/from-server/attributesChanged.ts", "../../networked-dom-protocol/src/networked-dom-v0.2/messages/from-server/batchEnd.ts", "../../networked-dom-protocol/src/networked-dom-v0.2/messages/from-server/batchStart.ts", "../../networked-dom-protocol/src/networked-dom-v0.2/messages/from-server/changeHiddenFrom.ts", "../../networked-dom-protocol/src/networked-dom-v0.2/messages/from-server/changeVisibleTo.ts", "../../networked-dom-protocol/src/networked-dom-v0.2/messages/from-server/childrenAdded.ts", "../../networked-dom-protocol/src/networked-dom-v0.2/messages/from-server/childrenRemoved.ts", "../../networked-dom-protocol/src/networked-dom-v0.2/messages/from-server/documentTime.ts", "../../networked-dom-protocol/src/networked-dom-v0.2/messages/from-server/error.ts", "../../networked-dom-protocol/src/networked-dom-v0.2/messages/from-server/ping.ts", "../../networked-dom-protocol/src/networked-dom-v0.2/messages/from-server/snapshot.ts", "../../networked-dom-protocol/src/networked-dom-v0.2/messages/from-server/textChanged.ts", "../../networked-dom-protocol/src/networked-dom-v0.2/messages/from-server/warning.ts", "../../networked-dom-protocol/src/networked-dom-v0.2/decodeServerMessages.ts", "../../networked-dom-protocol/src/networked-dom-v0.2/encodeClientMessage.ts", "../../networked-dom-protocol/src/networked-dom-v0.2/encodeServerMessage.ts", "../../networked-dom-web/src/DOMSanitizer.ts", "../../networked-dom-web/src/NetworkedDOMWebsocket.ts", "../../networked-dom-web/src/NetworkedDOMWebsocketV01Adapter.ts", "../../networked-dom-web/src/NetworkedDOMWebsocketV02Adapter.ts", "../src/index.ts"],
4
- "sourcesContent": ["export const networkedDOMProtocolSubProtocol_v0_1 = \"networked-dom-v0.1\";\n", "const textDecoder = new TextDecoder();\n\nexport class BufferReader {\n private buffer: Uint8Array;\n private offset: number;\n\n constructor(buffer: Uint8Array) {\n this.buffer = buffer;\n this.offset = 0;\n }\n\n public readUInt8(): number {\n return this.buffer[this.offset++];\n }\n\n public readBoolean(): boolean {\n return this.readUInt8() === 1;\n }\n\n public readUVarint(signed = false): number {\n let lo = 0;\n let hi = 0;\n let i = 0;\n for (; i < 4; ++i) {\n lo = (lo | ((this.buffer[this.offset] & 127) << (i * 7))) >>> 0;\n if (this.buffer[this.offset++] < 128) {\n return signed ? loAndHiAsSigned(lo, hi) : loAndHiAsUnsigned(lo, hi);\n }\n }\n lo = (lo | ((this.buffer[this.offset] & 127) << 28)) >>> 0;\n hi = (hi | ((this.buffer[this.offset] & 127) >> 4)) >>> 0;\n if (this.buffer[this.offset++] < 128) {\n return signed ? loAndHiAsSigned(lo, hi) : loAndHiAsUnsigned(lo, hi);\n }\n i = 0;\n for (; i < 5; ++i) {\n hi = (hi | ((this.buffer[this.offset] & 127) << (i * 7 + 3))) >>> 0;\n if (this.buffer[this.offset++] < 128) {\n return signed ? loAndHiAsSigned(lo, hi) : loAndHiAsUnsigned(lo, hi);\n }\n }\n\n throw Error(\"invalid varint encoding\");\n }\n\n public readUVarintPrefixedString(): string {\n const readLength = this.readUVarint();\n\n let string = \"\";\n let hasNonAscii = false;\n for (let i = 0; i < readLength; i++) {\n const charValue = this.buffer[this.offset + i];\n if (charValue < 0x80) {\n string += String.fromCharCode(charValue);\n } else {\n hasNonAscii = true;\n break;\n }\n }\n if (!hasNonAscii) {\n this.offset += readLength;\n return string;\n }\n\n // Slow path - decode the string using TextDecoder\n const result = textDecoder.decode(this.buffer.subarray(this.offset, this.offset + readLength));\n this.offset += readLength;\n return result;\n }\n\n // returns the string and a boolean indicating if the string was negative length\n public readVarintPrefixedString(): [string, boolean] {\n const length = this.readVarint();\n const negativeLength = length < 0;\n const readLength = negativeLength ? -length : length;\n\n let string = \"\";\n let hasNonAscii = false;\n for (let i = 0; i < readLength; i++) {\n const charValue = this.buffer[this.offset + i];\n if (charValue < 0x80) {\n string += String.fromCharCode(charValue);\n } else {\n hasNonAscii = true;\n break;\n }\n }\n if (!hasNonAscii) {\n this.offset += readLength;\n return [string, negativeLength];\n }\n\n // Slow path - decode the string using TextDecoder\n const result = textDecoder.decode(this.buffer.subarray(this.offset, this.offset + readLength));\n this.offset += readLength;\n return [result, negativeLength];\n }\n\n public readVarint(): number {\n return this.readUVarint(true);\n }\n\n public isEnd() {\n return this.offset >= this.buffer.length;\n }\n}\n\nfunction loAndHiAsSigned(lo: number, hi: number) {\n const value = lo + hi * 4294967296;\n if (value & 1) {\n return -(value + 1) / 2;\n }\n return value / 2;\n}\n\nfunction loAndHiAsUnsigned(lo: number, hi: number) {\n return lo + hi * 4294967296;\n}\n", "const textEncoder = new TextEncoder();\n\nexport class BufferWriter {\n private buffer: Uint8Array;\n private offset: number;\n\n constructor(initialLength: number) {\n this.buffer = new Uint8Array(initialLength);\n this.offset = 0;\n }\n\n // Write an unsigned 8-bit integer\n public writeUint8(value: number): void {\n this.ensureCapacity(1);\n this.buffer[this.offset] = value & 0xff;\n this.offset += 1;\n }\n\n public writeBoolean(bool: boolean) {\n this.writeUint8(bool ? 1 : 0);\n }\n\n // Write an array of bytes\n public writeBytes(bytes: Uint8Array): void {\n this.ensureCapacity(bytes.byteLength);\n this.buffer.set(bytes, this.offset);\n this.offset += bytes.byteLength;\n }\n\n // Get the written bytes as a Uint8Array\n public getBuffer(): Uint8Array {\n return this.buffer.subarray(0, this.offset);\n }\n\n public getWrittenLength(): number {\n return this.offset;\n }\n\n // Ensure there is enough capacity in the buffer\n private ensureCapacity(neededSpace: number): void {\n while (this.offset + neededSpace > this.buffer.length) {\n this.expandBuffer();\n }\n }\n\n // Expand the buffer by doubling its current length\n private expandBuffer(): void {\n const newBuffer = new Uint8Array(this.buffer.length * 2);\n newBuffer.set(this.buffer);\n this.buffer = newBuffer;\n }\n\n public writeUVarint(x: number) {\n if (x <= 268435455) {\n // Simple case that can be handled without hi and lo\n this.ensureCapacity(4);\n while (x >= 0x80) {\n this.buffer[this.offset] = (x & 0x7f) | 0x80; // Extract least significant 7 bits and set continuation bit\n this.offset++;\n x >>>= 7; // Use unsigned shift here\n }\n this.buffer[this.offset] = x & 0x7f; // No need for 0xff here since we're limiting it to 7 bits\n this.offset++;\n return;\n }\n this.ensureCapacity(10);\n\n let lo = 0;\n let hi = 0;\n if (x !== 0) {\n lo = x >>> 0;\n hi = ((x - lo) / 4294967296) >>> 0;\n }\n\n while (hi) {\n this.buffer[this.offset++] = (lo & 127) | 128;\n lo = ((lo >>> 7) | (hi << 25)) >>> 0;\n hi >>>= 7;\n }\n while (lo > 127) {\n this.buffer[this.offset++] = (lo & 127) | 128;\n lo = lo >>> 7;\n }\n this.buffer[this.offset++] = lo;\n }\n\n public writeVarint(x: number) {\n if (x >= 0) {\n this.writeUVarint(x * 2);\n } else {\n this.writeUVarint(-x * 2 - 1);\n }\n }\n\n public writeLengthPrefixedString(value: string, varint = false, negativeLength = false) {\n /*\n Try fast case first - no non-ascii characters and byte length is string length.\n\n Even if this case fails (non-ascii character found) the data will always be\n shorter so it can be overwritten\n */\n const originalOffset = this.offset; // store this in case we need to overwrite from here\n // Just write the length of the string (not the known encoded length)\n if (varint) {\n this.writeVarint(negativeLength ? -value.length : value.length);\n } else {\n this.writeUVarint(value.length);\n }\n this.ensureCapacity(value.length); // Ensure we have enough space for the string\n let nonAscii = false;\n for (let i = 0; i < value.length; i++) {\n const charCode = value.charCodeAt(i);\n if (charCode > 0x7f) {\n nonAscii = true;\n break;\n }\n this.buffer[this.offset++] = charCode;\n }\n\n if (!nonAscii) {\n return;\n }\n\n /*\n If we have non-ascii characters, we need to encode the string respecting\n utf-8 and overwrite the buffer from the original offset\n */\n this.offset = originalOffset; // overwrite the length\n let encodedLength = value.length; // This will be overwritten once we know the actual length\n this.ensureCapacity(encodedLength); // This will be at least the required length, but it gives the chance of initially creating a large enough buffer\n while (true) {\n this.offset = originalOffset;\n if (varint) {\n this.writeVarint(negativeLength ? -encodedLength : encodedLength);\n } else {\n this.writeUVarint(encodedLength);\n }\n const offsetAfterVarint = this.offset;\n const varintLength = offsetAfterVarint - originalOffset;\n\n const writeBuffer = new Uint8Array(this.buffer.buffer, this.offset);\n const { read, written } = textEncoder.encodeInto(value, writeBuffer);\n if (read !== value.length) {\n // Need more space and try again\n this.expandBuffer();\n continue;\n }\n if (written !== encodedLength) {\n encodedLength = written;\n // We need to overwrite the varint with the correct length\n this.offset = originalOffset;\n if (varint) {\n this.writeVarint(negativeLength ? -encodedLength : encodedLength);\n } else {\n this.writeUVarint(encodedLength);\n }\n const newOffsetAfterVarint = this.offset;\n const actualVarintLength = newOffsetAfterVarint - originalOffset;\n if (actualVarintLength !== varintLength) {\n // The varint length changed and it has overwritten the string\n // We need to write the string again\n continue;\n } else {\n // The varint length is the same so the string is intact\n }\n }\n // String written successfully - update the offset\n this.offset += written;\n return;\n }\n }\n}\n", "import { BufferReader } from \"../BufferReader\";\nimport { BufferWriter } from \"../BufferWriter\";\n\nexport function encodeAttribute(writer: BufferWriter, key: string, value: string | null) {\n if (value === null) {\n writer.writeLengthPrefixedString(key, true, true);\n } else {\n writer.writeLengthPrefixedString(key, true, false);\n writer.writeLengthPrefixedString(value);\n }\n}\n\nexport function encodeAttributes(writer: BufferWriter, attributes: Array<[string, string | null]>) {\n writer.writeUVarint(attributes.length);\n\n for (let i = 0; i < attributes.length; i++) {\n encodeAttribute(writer, attributes[i][0], attributes[i][1]);\n }\n}\n\nexport function decodeAttributes(buffer: BufferReader): Array<[string, string | null]> {\n const attributesLength = buffer.readUVarint();\n const attributes: Array<[string, string | null]> = [];\n for (let i = 0; i < attributesLength; i++) {\n const [key, negativeLength] = buffer.readVarintPrefixedString();\n if (negativeLength) {\n attributes.push([key, null]);\n continue;\n }\n const value = buffer.readUVarintPrefixedString();\n attributes.push([key, value]);\n }\n return attributes;\n}\n", "import { BufferReader } from \"../BufferReader\";\nimport { BufferWriter } from \"../BufferWriter\";\nimport { decodeAttributes, encodeAttributes } from \"./attributes\";\n\nexport type NetworkedDOMV02TextNodeDescription = {\n type: \"text\";\n nodeId: number;\n text: string;\n};\n\nexport type NetworkedDOMV02ElementNodeDescription = {\n type: \"element\";\n nodeId: number;\n tag: string;\n attributes: Array<[string, string | null]>;\n children: Array<NetworkedDOMV02NodeDescription>;\n visibleTo?: Array<number>;\n hiddenFrom?: Array<number>;\n text?: string;\n};\n\nexport type NetworkedDOMV02NodeDescription =\n | NetworkedDOMV02ElementNodeDescription\n | NetworkedDOMV02TextNodeDescription;\n\nexport function encodeNodeDescription(\n writer: BufferWriter,\n nodeDescription: NetworkedDOMV02NodeDescription,\n): void {\n writer.writeUVarint(nodeDescription.nodeId);\n\n if (nodeDescription.type === \"text\") {\n writer.writeLengthPrefixedString(\"\"); // Empty tag indicates text node\n writer.writeLengthPrefixedString(nodeDescription.text);\n return;\n }\n\n writer.writeLengthPrefixedString(nodeDescription.tag);\n\n encodeAttributes(writer, nodeDescription.attributes);\n\n if (!nodeDescription.visibleTo) {\n writer.writeUVarint(0);\n } else {\n writer.writeUVarint(nodeDescription.visibleTo.length);\n for (let i = 0; i < nodeDescription.visibleTo.length; i++) {\n writer.writeUVarint(nodeDescription.visibleTo[i]);\n }\n }\n\n if (!nodeDescription.hiddenFrom) {\n writer.writeUVarint(0);\n } else {\n writer.writeUVarint(nodeDescription.hiddenFrom.length);\n for (let i = 0; i < nodeDescription.hiddenFrom.length; i++) {\n writer.writeUVarint(nodeDescription.hiddenFrom[i]);\n }\n }\n\n writer.writeUVarint(nodeDescription.children.length);\n for (let i = 0; i < nodeDescription.children.length; i++) {\n encodeNodeDescription(writer, nodeDescription.children[i]);\n }\n}\n\nexport function decodeNodeDescription(buffer: BufferReader): NetworkedDOMV02NodeDescription {\n const nodeId = buffer.readUVarint();\n const tag = buffer.readUVarintPrefixedString();\n if (tag === \"\") {\n // Text node\n const text = buffer.readUVarintPrefixedString();\n return { type: \"text\", nodeId, text };\n }\n\n const attributes = decodeAttributes(buffer);\n\n const visibleToLength = buffer.readUVarint();\n let visibleTo: number[] | undefined;\n if (visibleToLength !== 0) {\n visibleTo = [];\n for (let i = 0; i < visibleToLength; i++) {\n visibleTo.push(buffer.readUVarint());\n }\n }\n\n const hiddenFromLength = buffer.readUVarint();\n let hiddenFrom: number[] | undefined;\n if (hiddenFromLength !== 0) {\n hiddenFrom = [];\n for (let i = 0; i < hiddenFromLength; i++) {\n hiddenFrom.push(buffer.readUVarint());\n }\n }\n\n const childrenLength = buffer.readUVarint();\n const children: NetworkedDOMV02NodeDescription[] = [];\n for (let i = 0; i < childrenLength; i++) {\n children.push(decodeNodeDescription(buffer));\n }\n\n const node: NetworkedDOMV02ElementNodeDescription = {\n type: \"element\",\n nodeId,\n tag,\n attributes,\n children,\n };\n\n if (visibleTo) {\n node.visibleTo = visibleTo;\n }\n if (hiddenFrom) {\n node.hiddenFrom = hiddenFrom;\n }\n\n return node;\n}\n", "export const networkedDOMProtocolSubProtocol_v0_2 = \"networked-dom-v0.2\";\n", "// Server -> Client\nexport const SnapshotMessageType = 1;\nexport const BatchStartMessageType = 2;\nexport const DocumentTimeMessageType = 3;\nexport const ChildrenAddedMessageType = 4;\nexport const ChildrenRemovedMessageType = 5;\nexport const AttributesChangedMessageType = 6;\nexport const ChangeVisibleToMessageType = 7;\nexport const ChangeHiddenFromMessageType = 8;\nexport const TextChangedMessageType = 9;\nexport const BatchEndMessageType = 10;\nexport const PingMessageType = 11;\nexport const WarningMessageType = 12;\nexport const ErrorMessageType = 13;\n\n// Client -> Server\nexport const ConnectUsersMessageType = 14;\nexport const DisconnectUsersMessageType = 15;\nexport const EventMessageType = 16;\nexport const PongMessageType = 17;\n", "import { BufferReader } from \"../../BufferReader\";\nimport { BufferWriter } from \"../../BufferWriter\";\nimport { ConnectUsersMessageType } from \"../../messageTypes\";\n\nexport type NetworkedDOMV02ConnectUsersMessage = {\n type: \"connectUsers\";\n connectionIds: Array<number>;\n};\n\nexport function encodeConnectUsers(\n connectUsersMessage: NetworkedDOMV02ConnectUsersMessage,\n writer: BufferWriter,\n) {\n const connectionIdsLength = connectUsersMessage.connectionIds.length;\n writer.writeUint8(ConnectUsersMessageType);\n writer.writeUVarint(connectionIdsLength);\n for (let i = 0; i < connectionIdsLength; i++) {\n writer.writeUVarint(connectUsersMessage.connectionIds[i]);\n }\n}\n\n// Assumes that the first byte has already been read (the message type)\nexport function decodeConnectUsers(buffer: BufferReader): NetworkedDOMV02ConnectUsersMessage {\n const connectionIds: number[] = [];\n const connectionIdsLength = buffer.readUVarint();\n for (let i = 0; i < connectionIdsLength; i++) {\n connectionIds.push(buffer.readUVarint());\n }\n return {\n type: \"connectUsers\",\n connectionIds,\n };\n}\n", "import { BufferReader } from \"../../BufferReader\";\nimport { BufferWriter } from \"../../BufferWriter\";\nimport { DisconnectUsersMessageType } from \"../../messageTypes\";\n\nexport type NetworkedDOMV02DisconnectUsersMessage = {\n type: \"disconnectUsers\";\n connectionIds: Array<number>;\n};\n\nexport function encodeDisconnectUsers(\n disconnectUsersMessage: NetworkedDOMV02DisconnectUsersMessage,\n writer: BufferWriter,\n) {\n const connectionIdsLength = disconnectUsersMessage.connectionIds.length;\n writer.writeUint8(DisconnectUsersMessageType);\n writer.writeUVarint(connectionIdsLength);\n for (let i = 0; i < connectionIdsLength; i++) {\n writer.writeUVarint(disconnectUsersMessage.connectionIds[i]);\n }\n}\n\n// Assumes that the first byte has already been read (the message type)\nexport function decodeDisconnectUsers(buffer: BufferReader): NetworkedDOMV02DisconnectUsersMessage {\n const connectionIds: number[] = [];\n const connectionIdsLength = buffer.readUVarint();\n for (let i = 0; i < connectionIdsLength; i++) {\n connectionIds.push(buffer.readUVarint());\n }\n return {\n type: \"disconnectUsers\",\n connectionIds,\n };\n}\n", "import { BufferReader } from \"../../BufferReader\";\nimport { BufferWriter } from \"../../BufferWriter\";\nimport { EventMessageType } from \"../../messageTypes\";\n\nexport type NetworkedDOMV02RemoteEvent = {\n type: \"event\";\n connectionId: number;\n nodeId: number;\n name: string;\n bubbles: boolean;\n params: any;\n};\n\nexport function encodeEvent(event: NetworkedDOMV02RemoteEvent, writer: BufferWriter) {\n writer.writeUint8(EventMessageType);\n writer.writeUVarint(event.nodeId);\n writer.writeUVarint(event.connectionId);\n writer.writeLengthPrefixedString(event.name);\n writer.writeBoolean(event.bubbles);\n writer.writeLengthPrefixedString(JSON.stringify(event.params));\n}\n\n// Assumes that the first byte has already been read (the message type)\nexport function decodeEvent(buffer: BufferReader): NetworkedDOMV02RemoteEvent {\n const nodeId = buffer.readUVarint();\n const connectionId = buffer.readUVarint();\n const name = buffer.readUVarintPrefixedString();\n const bubbles = buffer.readBoolean();\n const paramsJSONString = buffer.readUVarintPrefixedString();\n const params = JSON.parse(paramsJSONString);\n return {\n type: \"event\",\n nodeId,\n connectionId,\n name,\n bubbles,\n params,\n };\n}\n", "import { BufferReader } from \"../../BufferReader\";\nimport { BufferWriter } from \"../../BufferWriter\";\nimport { PongMessageType } from \"../../messageTypes\";\n\nexport type NetworkedDOMV02PongMessage = {\n type: \"pong\";\n pong: number;\n};\n\nexport function encodePong(pongMessage: NetworkedDOMV02PongMessage, writer: BufferWriter) {\n writer.writeUint8(PongMessageType);\n writer.writeUVarint(pongMessage.pong);\n}\n\n// Assumes that the first byte has already been read (the message type)\nexport function decodePong(buffer: BufferReader): NetworkedDOMV02PongMessage {\n const pong = buffer.readUVarint();\n return {\n type: \"pong\",\n pong,\n };\n}\n", "import { BufferReader } from \"./BufferReader\";\nimport { NetworkedDOMV02ClientMessage } from \"./messages\";\nimport { decodeConnectUsers } from \"./messages/from-client/connectUsers\";\nimport { decodeDisconnectUsers } from \"./messages/from-client/disconnectUsers\";\nimport { decodeEvent } from \"./messages/from-client/event\";\nimport { decodePong } from \"./messages/from-client/pong\";\nimport {\n ConnectUsersMessageType,\n DisconnectUsersMessageType,\n EventMessageType,\n PongMessageType,\n} from \"./messageTypes\";\n\nexport function decodeClientMessages(buffer: BufferReader): Array<NetworkedDOMV02ClientMessage> {\n const messages: NetworkedDOMV02ClientMessage[] = [];\n while (!buffer.isEnd()) {\n const messageType = buffer.readUInt8();\n switch (messageType) {\n case ConnectUsersMessageType:\n messages.push(decodeConnectUsers(buffer));\n break;\n case DisconnectUsersMessageType:\n messages.push(decodeDisconnectUsers(buffer));\n break;\n case EventMessageType:\n messages.push(decodeEvent(buffer));\n break;\n case PongMessageType:\n messages.push(decodePong(buffer));\n break;\n default:\n throw new Error(`Unknown message type: ${messageType}`);\n }\n }\n return messages;\n}\n", "import { BufferReader } from \"../../BufferReader\";\nimport { BufferWriter } from \"../../BufferWriter\";\nimport { decodeAttributes, encodeAttributes } from \"../../common-structs/attributes\";\nimport { AttributesChangedMessageType } from \"../../messageTypes\";\n\nexport type NetworkedDOMV02AttributesChangedDiff = {\n type: \"attributesChanged\";\n nodeId: number;\n attributes: Array<[string, string | null]>;\n documentTime?: number;\n};\n\nexport function encodeAttributesChanged(\n msg: NetworkedDOMV02AttributesChangedDiff,\n writer: BufferWriter = new BufferWriter(64),\n): BufferWriter {\n writer.writeUint8(AttributesChangedMessageType);\n writer.writeUVarint(msg.nodeId);\n encodeAttributes(writer, msg.attributes);\n return writer;\n}\n\n// Assumes that the first byte has already been read (the message type)\nexport function decodeAttributesChanged(\n buffer: BufferReader,\n): NetworkedDOMV02AttributesChangedDiff {\n const nodeId = buffer.readUVarint();\n const attributes = decodeAttributes(buffer);\n return {\n type: \"attributesChanged\",\n nodeId,\n attributes,\n };\n}\n", "import { BufferWriter } from \"../../BufferWriter\";\nimport { BatchEndMessageType } from \"../../messageTypes\";\n\nexport type NetworkedDOMV02BatchEndMessage = {\n type: \"batchEnd\";\n};\n\nexport function encodeBatchEnd(writer: BufferWriter = new BufferWriter(1)): BufferWriter {\n writer.writeUint8(BatchEndMessageType);\n return writer;\n}\n\nexport const batchEndMessage: NetworkedDOMV02BatchEndMessage = {\n type: \"batchEnd\",\n};\n", "import { BufferWriter } from \"../../BufferWriter\";\nimport { BatchStartMessageType } from \"../../messageTypes\";\n\nexport type NetworkedDOMV02BatchStartMessage = {\n type: \"batchStart\";\n};\n\nexport function encodeBatchStart(writer: BufferWriter = new BufferWriter(1)): BufferWriter {\n writer.writeUint8(BatchStartMessageType);\n return writer;\n}\n\nexport const batchStartMessage: NetworkedDOMV02BatchStartMessage = {\n type: \"batchStart\",\n};\n", "import { BufferReader } from \"../../BufferReader\";\nimport { BufferWriter } from \"../../BufferWriter\";\nimport { ChangeHiddenFromMessageType } from \"../../messageTypes\";\n\nexport type NetworkedDOMV02ChangeHiddenFromDiff = {\n type: \"changeHiddenFrom\";\n nodeId: number;\n addHiddenFrom: Array<number>;\n removeHiddenFrom: Array<number>;\n};\n\nexport function encodeChangeHiddenFrom(\n msg: NetworkedDOMV02ChangeHiddenFromDiff,\n writer: BufferWriter = new BufferWriter(64),\n): BufferWriter {\n writer.writeUint8(ChangeHiddenFromMessageType);\n writer.writeUVarint(msg.nodeId);\n\n if (msg.addHiddenFrom) {\n writer.writeUVarint(msg.addHiddenFrom.length);\n\n for (const key of msg.addHiddenFrom) {\n writer.writeUVarint(key);\n }\n } else {\n // If there are no addHiddenFrom, we still need to send a 0 to indicate that there are no entries\n writer.writeUVarint(0);\n }\n if (msg.removeHiddenFrom) {\n writer.writeUVarint(msg.removeHiddenFrom.length);\n\n for (const key of msg.removeHiddenFrom) {\n writer.writeUVarint(key);\n }\n } else {\n // If there are no removeHiddenFrom, we still need to send a 0 to indicate that there are no entries\n writer.writeUVarint(0);\n }\n return writer;\n}\n\n// Assumes that the first byte has already been read (the message type)\nexport function decodeChangeHiddenFrom(buffer: BufferReader): NetworkedDOMV02ChangeHiddenFromDiff {\n const nodeId = buffer.readUVarint();\n const addHiddenFromLength = buffer.readUVarint();\n const addHiddenFrom: number[] = [];\n for (let i = 0; i < addHiddenFromLength; i++) {\n addHiddenFrom.push(buffer.readUVarint());\n }\n\n const removeHiddenFromLength = buffer.readUVarint();\n const removeHiddenFrom: number[] = [];\n for (let i = 0; i < removeHiddenFromLength; i++) {\n removeHiddenFrom.push(buffer.readUVarint());\n }\n\n return {\n type: \"changeHiddenFrom\",\n nodeId,\n addHiddenFrom,\n removeHiddenFrom,\n };\n}\n", "import { BufferReader } from \"../../BufferReader\";\nimport { BufferWriter } from \"../../BufferWriter\";\nimport { ChangeVisibleToMessageType } from \"../../messageTypes\";\n\nexport type NetworkedDOMV02ChangeVisibleToDiff = {\n type: \"changeVisibleTo\";\n nodeId: number;\n /*\n The semantics are that if there are no visibleTo limitations then the node is visible to everyone.\n\n It is advisable to apply the addVisibleTo first before the removeVisibleTo to avoid even a temporary state where a node is visible to everyone between the two operations.\n */\n addVisibleTo: Array<number>;\n removeVisibleTo: Array<number>;\n};\n\nexport function encodeChangeVisibleTo(\n msg: NetworkedDOMV02ChangeVisibleToDiff,\n writer: BufferWriter = new BufferWriter(64),\n): BufferWriter {\n writer.writeUint8(ChangeVisibleToMessageType);\n writer.writeUVarint(msg.nodeId);\n\n if (msg.addVisibleTo) {\n writer.writeUVarint(msg.addVisibleTo.length);\n\n for (const key of msg.addVisibleTo) {\n writer.writeUVarint(key);\n }\n } else {\n // If there are no addVisibleTo, we still need to send a 0 to indicate that there are no entries\n writer.writeUVarint(0);\n }\n if (msg.removeVisibleTo) {\n writer.writeUVarint(msg.removeVisibleTo.length);\n\n for (const key of msg.removeVisibleTo) {\n writer.writeUVarint(key);\n }\n } else {\n // If there are no removeVisibleTo, we still need to send a 0 to indicate that there are no entries\n writer.writeUVarint(0);\n }\n return writer;\n}\n\n// Assumes that the first byte has already been read (the message type)\nexport function decodeChangeVisibleTo(buffer: BufferReader): NetworkedDOMV02ChangeVisibleToDiff {\n const nodeId = buffer.readUVarint();\n const addVisibleToLength = buffer.readUVarint();\n const addVisibleTo: number[] = [];\n for (let i = 0; i < addVisibleToLength; i++) {\n addVisibleTo.push(buffer.readUVarint());\n }\n\n const removeVisibleToLength = buffer.readUVarint();\n const removeVisibleTo: number[] = [];\n for (let i = 0; i < removeVisibleToLength; i++) {\n removeVisibleTo.push(buffer.readUVarint());\n }\n\n return {\n type: \"changeVisibleTo\",\n nodeId,\n addVisibleTo,\n removeVisibleTo,\n };\n}\n", "import { BufferReader } from \"../../BufferReader\";\nimport { BufferWriter } from \"../../BufferWriter\";\nimport {\n decodeNodeDescription,\n encodeNodeDescription,\n NetworkedDOMV02NodeDescription,\n} from \"../../common-structs/nodeDescription\";\nimport { ChildrenAddedMessageType } from \"../../messageTypes\";\n\nexport type NetworkedDOMV02ChildrenAddedDiff = {\n type: \"childrenAdded\";\n nodeId: number;\n previousNodeId: number | null;\n addedNodes: Array<NetworkedDOMV02NodeDescription>;\n};\n\nexport function encodeChildrenAdded(\n msg: NetworkedDOMV02ChildrenAddedDiff,\n writer: BufferWriter = new BufferWriter(64),\n): BufferWriter {\n writer.writeUint8(ChildrenAddedMessageType);\n writer.writeUVarint(msg.nodeId);\n writer.writeUVarint(msg.previousNodeId ?? 0);\n writer.writeUVarint(msg.addedNodes.length);\n for (let i = 0; i < msg.addedNodes.length; i++) {\n encodeNodeDescription(writer, msg.addedNodes[i]);\n }\n return writer;\n}\n\n// Assumes that the first byte has already been read (the message type)\nexport function decodeChildrenAdded(buffer: BufferReader): NetworkedDOMV02ChildrenAddedDiff {\n const nodeId = buffer.readUVarint();\n const previousNodeId = buffer.readUVarint();\n const childrenLength = buffer.readUVarint();\n const children: NetworkedDOMV02NodeDescription[] = [];\n for (let i = 0; i < childrenLength; i++) {\n children.push(decodeNodeDescription(buffer));\n }\n return {\n type: \"childrenAdded\",\n nodeId,\n previousNodeId: previousNodeId === 0 ? null : previousNodeId,\n addedNodes: children,\n };\n}\n", "import { BufferReader } from \"../../BufferReader\";\nimport { BufferWriter } from \"../../BufferWriter\";\nimport { ChildrenRemovedMessageType } from \"../../messageTypes\";\n\nexport type NetworkedDOMV02ChildrenRemovedDiff = {\n type: \"childrenRemoved\";\n nodeId: number;\n removedNodes: Array<number>;\n documentTime?: number;\n};\n\nexport function encodeChildrenRemoved(\n msg: NetworkedDOMV02ChildrenRemovedDiff,\n writer: BufferWriter = new BufferWriter(64),\n): BufferWriter {\n writer.writeUint8(ChildrenRemovedMessageType);\n writer.writeUVarint(msg.nodeId);\n writer.writeUVarint(msg.removedNodes.length);\n for (const nodeId of msg.removedNodes) {\n writer.writeUVarint(nodeId);\n }\n return writer;\n}\n\n// Assumes that the first byte has already been read (the message type)\nexport function decodeChildrenRemoved(buffer: BufferReader): NetworkedDOMV02ChildrenRemovedDiff {\n const nodeId = buffer.readUVarint();\n const removedNodesLength = buffer.readUVarint();\n const removedNodes: number[] = [];\n for (let i = 0; i < removedNodesLength; i++) {\n removedNodes.push(buffer.readUVarint());\n }\n return {\n type: \"childrenRemoved\",\n nodeId,\n removedNodes,\n };\n}\n", "import { BufferReader } from \"../../BufferReader\";\nimport { BufferWriter } from \"../../BufferWriter\";\nimport { DocumentTimeMessageType } from \"../../messageTypes\";\n\nexport type NetworkedDOMV02DocumentTimeMessage = {\n type: \"documentTime\";\n documentTime: number;\n};\n\nexport function encodeDocumentTime(\n msg: NetworkedDOMV02DocumentTimeMessage,\n writer: BufferWriter = new BufferWriter(8),\n): BufferWriter {\n writer.writeUint8(DocumentTimeMessageType);\n writer.writeUVarint(msg.documentTime);\n return writer;\n}\n\n// Assumes that the first byte has already been read (the message type)\nexport function decodeDocumentTime(buffer: BufferReader): NetworkedDOMV02DocumentTimeMessage {\n return {\n type: \"documentTime\",\n documentTime: buffer.readUVarint(),\n };\n}\n", "import { BufferReader } from \"../../BufferReader\";\nimport { BufferWriter } from \"../../BufferWriter\";\nimport { ErrorMessageType } from \"../../messageTypes\";\n\nexport type NetworkedDOMV02ErrorMessage = {\n type: \"error\";\n message: string;\n};\n\nexport function encodeError(\n msg: NetworkedDOMV02ErrorMessage,\n writer: BufferWriter = new BufferWriter(64),\n): BufferWriter {\n writer.writeUint8(ErrorMessageType);\n writer.writeLengthPrefixedString(msg.message);\n return writer;\n}\n\n// Assumes that the first byte has already been read (the message type)\nexport function decodeError(buffer: BufferReader): NetworkedDOMV02ErrorMessage {\n const message = buffer.readUVarintPrefixedString();\n return {\n type: \"error\",\n message,\n };\n}\n", "import { BufferReader } from \"../../BufferReader\";\nimport { BufferWriter } from \"../../BufferWriter\";\nimport { PingMessageType } from \"../../messageTypes\";\n\nexport type NetworkedDOMV02PingMessage = {\n type: \"ping\";\n ping: number;\n documentTime: number;\n};\n\nexport function encodePing(\n pingMessage: NetworkedDOMV02PingMessage,\n writer: BufferWriter = new BufferWriter(8),\n): BufferWriter {\n writer.writeUint8(PingMessageType);\n writer.writeUVarint(pingMessage.ping);\n writer.writeUVarint(pingMessage.documentTime);\n return writer;\n}\n\n// Assumes that the first byte has already been read (the message type)\nexport function decodePing(buffer: BufferReader): NetworkedDOMV02PingMessage {\n const ping = buffer.readUVarint();\n const documentTime = buffer.readUVarint();\n return {\n type: \"ping\",\n ping,\n documentTime,\n };\n}\n", "import { BufferReader } from \"../../BufferReader\";\nimport { BufferWriter } from \"../../BufferWriter\";\nimport {\n decodeNodeDescription,\n encodeNodeDescription,\n NetworkedDOMV02ElementNodeDescription,\n NetworkedDOMV02NodeDescription,\n} from \"../../common-structs/nodeDescription\";\nimport { SnapshotMessageType } from \"../../messageTypes\";\n\nexport type NetworkedDOMV02SnapshotMessage = {\n type: \"snapshot\";\n snapshot: NetworkedDOMV02NodeDescription;\n documentTime: number;\n};\n\nexport function encodeSnapshot(\n msg: NetworkedDOMV02SnapshotMessage,\n writer: BufferWriter = new BufferWriter(64),\n): BufferWriter {\n writer.writeUint8(SnapshotMessageType);\n encodeNodeDescription(writer, msg.snapshot as NetworkedDOMV02ElementNodeDescription);\n writer.writeUVarint(msg.documentTime);\n return writer;\n}\n\n// Assumes that the first byte has already been read (the message type)\nexport function decodeSnapshot(buffer: BufferReader): NetworkedDOMV02SnapshotMessage {\n return {\n type: \"snapshot\",\n snapshot: decodeNodeDescription(buffer),\n documentTime: buffer.readUVarint(),\n };\n}\n", "import { BufferReader } from \"../../BufferReader\";\nimport { BufferWriter } from \"../../BufferWriter\";\nimport { TextChangedMessageType } from \"../../messageTypes\";\n\nexport type NetworkedDOMV02TextChangedDiff = {\n type: \"textChanged\";\n nodeId: number;\n text: string;\n};\n\nexport function encodeTextChanged(\n msg: NetworkedDOMV02TextChangedDiff,\n writer: BufferWriter = new BufferWriter(64),\n): BufferWriter {\n writer.writeUint8(TextChangedMessageType);\n writer.writeUVarint(msg.nodeId);\n writer.writeLengthPrefixedString(msg.text);\n return writer;\n}\n\n// Assumes that the first byte has already been read (the message type)\nexport function decodeTextChanged(buffer: BufferReader): NetworkedDOMV02TextChangedDiff {\n const nodeId = buffer.readUVarint();\n const text = buffer.readUVarintPrefixedString();\n return {\n type: \"textChanged\",\n nodeId,\n text,\n };\n}\n", "import { BufferReader } from \"../../BufferReader\";\nimport { BufferWriter } from \"../../BufferWriter\";\nimport { WarningMessageType } from \"../../messageTypes\";\n\nexport type NetworkedDOMV02WarningMessage = {\n type: \"warning\";\n message: string;\n};\n\nexport function encodeWarning(\n msg: NetworkedDOMV02WarningMessage,\n writer: BufferWriter = new BufferWriter(64),\n): BufferWriter {\n writer.writeUint8(WarningMessageType);\n writer.writeLengthPrefixedString(msg.message);\n return writer;\n}\n\n// Assumes that the first byte has already been read (the message type)\nexport function decodeWarning(buffer: BufferReader): NetworkedDOMV02WarningMessage {\n const message = buffer.readUVarintPrefixedString();\n return {\n type: \"warning\",\n message,\n };\n}\n", "import { BufferReader } from \"./BufferReader\";\nimport {\n batchEndMessage,\n batchStartMessage,\n decodeAttributesChanged,\n decodeChangeHiddenFrom,\n decodeChangeVisibleTo,\n decodeChildrenAdded,\n decodeChildrenRemoved,\n decodeError,\n decodePing,\n decodeSnapshot,\n decodeTextChanged,\n decodeWarning,\n NetworkedDOMV02ServerMessage,\n} from \"./messages\";\nimport { decodeDocumentTime } from \"./messages/from-server/documentTime\";\nimport {\n AttributesChangedMessageType,\n BatchEndMessageType,\n BatchStartMessageType,\n ChangeHiddenFromMessageType,\n ChangeVisibleToMessageType,\n ChildrenAddedMessageType,\n ChildrenRemovedMessageType,\n DocumentTimeMessageType,\n ErrorMessageType,\n PingMessageType,\n SnapshotMessageType,\n TextChangedMessageType,\n WarningMessageType,\n} from \"./messageTypes\";\n\nexport function decodeServerMessages(buffer: BufferReader): Array<NetworkedDOMV02ServerMessage> {\n const messages: NetworkedDOMV02ServerMessage[] = [];\n while (!buffer.isEnd()) {\n const messageType = buffer.readUInt8();\n switch (messageType) {\n case SnapshotMessageType:\n messages.push(decodeSnapshot(buffer));\n break;\n case DocumentTimeMessageType:\n messages.push(decodeDocumentTime(buffer));\n break;\n case ChildrenAddedMessageType:\n messages.push(decodeChildrenAdded(buffer));\n break;\n case ChildrenRemovedMessageType:\n messages.push(decodeChildrenRemoved(buffer));\n break;\n case AttributesChangedMessageType:\n messages.push(decodeAttributesChanged(buffer));\n break;\n case TextChangedMessageType:\n messages.push(decodeTextChanged(buffer));\n break;\n case ChangeVisibleToMessageType:\n messages.push(decodeChangeVisibleTo(buffer));\n break;\n case ChangeHiddenFromMessageType:\n messages.push(decodeChangeHiddenFrom(buffer));\n break;\n case BatchStartMessageType:\n messages.push(batchStartMessage);\n break;\n case BatchEndMessageType:\n messages.push(batchEndMessage);\n break;\n case PingMessageType:\n messages.push(decodePing(buffer));\n break;\n case WarningMessageType:\n messages.push(decodeWarning(buffer));\n break;\n case ErrorMessageType:\n messages.push(decodeError(buffer));\n break;\n default:\n throw new Error(`Unknown message type: ${messageType}`);\n }\n }\n return messages;\n}\n", "import { BufferWriter } from \"./BufferWriter\";\nimport {\n encodeConnectUsers,\n encodeDisconnectUsers,\n encodeEvent,\n encodePong,\n NetworkedDOMV02ClientMessage,\n} from \"./messages\";\n\nexport function encodeClientMessage(message: NetworkedDOMV02ClientMessage, writer: BufferWriter) {\n const type = message.type;\n switch (type) {\n case \"connectUsers\":\n return encodeConnectUsers(message, writer);\n case \"disconnectUsers\":\n return encodeDisconnectUsers(message, writer);\n case \"event\":\n return encodeEvent(message, writer);\n case \"pong\":\n return encodePong(message, writer);\n default:\n throw new Error(`Unknown message type: ${type}`);\n }\n}\n", "import { BufferWriter } from \"./BufferWriter\";\nimport {\n encodeBatchEnd,\n encodeBatchStart,\n encodeTextChanged,\n NetworkedDOMV02ServerMessage,\n} from \"./messages\";\nimport { encodeAttributesChanged } from \"./messages/from-server/attributesChanged\";\nimport { encodeChangeHiddenFrom } from \"./messages/from-server/changeHiddenFrom\";\nimport { encodeChangeVisibleTo } from \"./messages/from-server/changeVisibleTo\";\nimport { encodeChildrenAdded } from \"./messages/from-server/childrenAdded\";\nimport { encodeChildrenRemoved } from \"./messages/from-server/childrenRemoved\";\nimport { encodeDocumentTime } from \"./messages/from-server/documentTime\";\nimport { encodeError } from \"./messages/from-server/error\";\nimport { encodePing } from \"./messages/from-server/ping\";\nimport { encodeSnapshot } from \"./messages/from-server/snapshot\";\nimport { encodeWarning } from \"./messages/from-server/warning\";\n\nexport function encodeServerMessage(\n message: NetworkedDOMV02ServerMessage,\n writer?: BufferWriter,\n): BufferWriter {\n switch (message.type) {\n case \"snapshot\":\n return encodeSnapshot(message, writer);\n case \"documentTime\":\n return encodeDocumentTime(message, writer);\n case \"childrenAdded\":\n return encodeChildrenAdded(message, writer);\n case \"childrenRemoved\":\n return encodeChildrenRemoved(message, writer);\n case \"attributesChanged\":\n return encodeAttributesChanged(message, writer);\n case \"textChanged\":\n return encodeTextChanged(message, writer);\n case \"changeVisibleTo\":\n return encodeChangeVisibleTo(message, writer);\n case \"changeHiddenFrom\":\n return encodeChangeHiddenFrom(message, writer);\n case \"batchStart\":\n return encodeBatchStart(writer);\n case \"batchEnd\":\n return encodeBatchEnd(writer);\n case \"ping\":\n return encodePing(message, writer);\n case \"warning\":\n return encodeWarning(message, writer);\n case \"error\":\n return encodeError(message, writer);\n default:\n throw new Error(`Unknown message type: ${(message as any).type}`);\n }\n}\n", "export type DOMSanitizerOptions = {\n tagPrefix?: string; // e.g. \"m-\" to restrict to only custom elements with a tag name starting with \"m-\"\n replacementTagPrefix?: string; // e.g. \"x-\" to replace non-prefixed tags with a new prefix (e.g. \"div\" -> \"x-div\")\n};\n\nexport class DOMSanitizer {\n static sanitise(node: HTMLElement, options: DOMSanitizerOptions = {}) {\n if (node.getAttributeNames) {\n for (const attr of node.getAttributeNames()) {\n if (!DOMSanitizer.IsValidAttributeName(attr)) {\n node.removeAttribute(attr);\n }\n }\n }\n\n if (node instanceof HTMLElement) {\n if (options.tagPrefix) {\n const tag = node.nodeName.toLowerCase();\n if (!tag.startsWith(options.tagPrefix.toLowerCase())) {\n node = DOMSanitizer.replaceNodeTagName(\n node,\n options.replacementTagPrefix ? options.replacementTagPrefix + tag : `x-${tag}`,\n );\n }\n }\n }\n\n if (node.nodeName === \"SCRIPT\" || node.nodeName === \"OBJECT\" || node.nodeName === \"IFRAME\") {\n // set contents to empty string\n node.innerHTML = \"\";\n DOMSanitizer.stripAllAttributes(node);\n } else {\n if (node.getAttributeNames) {\n for (const attr of node.getAttributeNames()) {\n if (!DOMSanitizer.shouldAcceptAttribute(attr)) {\n node.removeAttribute(attr);\n }\n }\n }\n for (let i = 0; i < node.childNodes.length; i++) {\n DOMSanitizer.sanitise(node.childNodes[i] as HTMLElement, options);\n }\n }\n return node;\n }\n\n static replaceNodeTagName(node: HTMLElement, newTagName: string) {\n const replacementNode = document.createElement(newTagName);\n let index;\n while (node.firstChild) {\n replacementNode.appendChild(node.firstChild);\n }\n for (index = node.attributes.length - 1; index >= 0; --index) {\n replacementNode.setAttribute(node.attributes[index].name, node.attributes[index].value);\n }\n node.parentNode?.replaceChild(replacementNode, node);\n return replacementNode;\n }\n\n static stripAllAttributes(node: HTMLElement) {\n if (node.getAttributeNames) {\n for (const attr of node.getAttributeNames()) {\n node.removeAttribute(attr);\n }\n }\n }\n\n static IsASCIIDigit(c: string): boolean {\n return c >= \"0\" && c <= \"9\";\n }\n\n static IsASCIIAlpha(c: string) {\n return c >= \"a\" && c <= \"z\";\n }\n\n static IsValidAttributeName(characters: string): boolean {\n const c = characters[0];\n if (!(DOMSanitizer.IsASCIIAlpha(c) || c === \":\" || c === \"_\")) {\n return false;\n }\n\n for (let i = 1; i < characters.length; i++) {\n const c = characters[i];\n if (\n !(\n DOMSanitizer.IsASCIIDigit(c) ||\n DOMSanitizer.IsASCIIAlpha(c) ||\n c === \":\" ||\n c === \"_\" ||\n c === \"-\" ||\n c === \".\"\n )\n ) {\n return false;\n }\n }\n\n return true;\n }\n\n static shouldAcceptAttribute(attribute: string) {\n if (!DOMSanitizer.IsValidAttributeName(attribute)) {\n console.warn(\"Invalid attribute name\", attribute);\n return false;\n }\n\n // TODO - this might be overly restrictive - apologies to someone that finds this because you have a non-event attribute filtered by this\n return !attribute.startsWith(\"on\");\n }\n}\n", "import {\n networkedDOMProtocolSubProtocol_v0_1,\n networkedDOMProtocolSubProtocol_v0_2,\n} from \"@mml-io/networked-dom-protocol\";\n\nimport { NetworkedDOMWebsocketV01Adapter } from \"./NetworkedDOMWebsocketV01Adapter\";\nimport { NetworkedDOMWebsocketV02Adapter } from \"./NetworkedDOMWebsocketV02Adapter\";\n\nconst startingBackoffTimeMilliseconds = 100;\nconst maximumBackoffTimeMilliseconds = 10000;\nconst maximumWebsocketConnectionTimeout = 5000;\n\nexport type NetworkedDOMWebsocketFactory = (url: string) => WebSocket;\n\nexport enum NetworkedDOMWebsocketStatus {\n Connecting,\n ConnectionOpen, // The websocket is open and connected, but no messages have been received yet\n Connected, // The websocket is open and connected, and messages are being received\n Reconnecting,\n Disconnected,\n}\n\nexport function NetworkedDOMWebsocketStatusToString(status: NetworkedDOMWebsocketStatus): string {\n switch (status) {\n case NetworkedDOMWebsocketStatus.Connecting:\n return \"Connecting...\";\n case NetworkedDOMWebsocketStatus.ConnectionOpen:\n return \"Connection Open\";\n case NetworkedDOMWebsocketStatus.Connected:\n return \"Connected\";\n case NetworkedDOMWebsocketStatus.Reconnecting:\n return \"Reconnecting...\";\n case NetworkedDOMWebsocketStatus.Disconnected:\n return \"Disconnected\";\n default:\n return \"Unknown\";\n }\n}\n\nexport type NetworkedDOMWebsocketOptions = {\n tagPrefix?: string; // e.g. \"m-\" to restrict to only custom elements with a tag name starting with \"m-\"\n replacementTagPrefix?: string; // e.g. \"x-\" to replace non-prefixed tags with a new prefix (e.g. \"div\" -> \"x-div\")\n};\n\nexport type NetworkedDOMWebsocketAdapter = {\n receiveMessage: (message: MessageEvent) => void;\n handleEvent: (element: HTMLElement, event: CustomEvent<{ element: HTMLElement }>) => void;\n clearContents: () => boolean;\n};\n\n/**\n * NetworkedDOMWebsocket is a client for a NetworkedDOMServer. It connects to a server on the provided url and receives\n * updates to the DOM. It also sends events to the server for interactions with the DOM.\n *\n * The NetworkedDOMWebsocket is attached to a parentElement and synchronizes the received DOM under that element.\n */\nexport class NetworkedDOMWebsocket {\n private websocket: WebSocket | null = null;\n private websocketAdapter: NetworkedDOMWebsocketAdapter | null = null;\n\n private stopped = false;\n private backoffTime = startingBackoffTimeMilliseconds;\n private status: NetworkedDOMWebsocketStatus | null = null;\n\n public static createWebSocket(url: string): WebSocket {\n return new WebSocket(url, [\n networkedDOMProtocolSubProtocol_v0_2,\n networkedDOMProtocolSubProtocol_v0_1,\n ]);\n }\n\n constructor(\n private url: string,\n private websocketFactory: NetworkedDOMWebsocketFactory,\n private parentElement: HTMLElement,\n private timeCallback?: (time: number) => void,\n private statusUpdateCallback?: (status: NetworkedDOMWebsocketStatus) => void,\n private options: NetworkedDOMWebsocketOptions = {},\n ) {\n this.setStatus(NetworkedDOMWebsocketStatus.Connecting);\n this.startWebSocketConnectionAttempt();\n }\n\n private setStatus(status: NetworkedDOMWebsocketStatus) {\n if (this.status !== status) {\n this.status = status;\n if (this.statusUpdateCallback) {\n this.statusUpdateCallback(status);\n }\n }\n }\n\n private createWebsocketWithTimeout(timeout: number): Promise<WebSocket> {\n return new Promise((resolve, reject) => {\n const websocket = this.websocketFactory(this.url);\n const timeoutId = setTimeout(() => {\n reject(new Error(\"websocket connection timed out\"));\n websocket.close();\n }, timeout);\n websocket.binaryType = \"arraybuffer\";\n websocket.addEventListener(\"open\", () => {\n clearTimeout(timeoutId);\n\n this.websocket = websocket;\n const isV02 = websocket.protocol === networkedDOMProtocolSubProtocol_v0_2;\n let websocketAdapter: NetworkedDOMWebsocketAdapter;\n if (isV02) {\n websocketAdapter = new NetworkedDOMWebsocketV02Adapter(\n websocket,\n this.parentElement,\n () => {\n this.backoffTime = startingBackoffTimeMilliseconds;\n this.setStatus(NetworkedDOMWebsocketStatus.Connected);\n },\n this.timeCallback,\n this.options,\n );\n } else {\n websocketAdapter = new NetworkedDOMWebsocketV01Adapter(\n websocket,\n this.parentElement,\n () => {\n this.backoffTime = startingBackoffTimeMilliseconds;\n this.setStatus(NetworkedDOMWebsocketStatus.Connected);\n },\n this.timeCallback,\n this.options,\n );\n }\n this.websocketAdapter = websocketAdapter;\n\n websocket.addEventListener(\"message\", (event) => {\n if (websocket !== this.websocket) {\n console.log(\"Ignoring websocket message event because it is no longer current\");\n websocket.close();\n return;\n }\n websocketAdapter.receiveMessage(event);\n });\n\n const onWebsocketClose = async () => {\n let hadContents = false;\n if (this.websocketAdapter) {\n hadContents = this.websocketAdapter.clearContents();\n }\n if (this.stopped) {\n // This closing is expected. The client closed the websocket.\n this.setStatus(NetworkedDOMWebsocketStatus.Disconnected);\n return;\n }\n if (!hadContents) {\n // The websocket did not deliver any contents. It may have been successfully opened, but immediately closed. This client should back off to prevent this happening in a rapid loop.\n await this.waitBackoffTime();\n }\n // The websocket closed unexpectedly. Try to reconnect.\n this.setStatus(NetworkedDOMWebsocketStatus.Reconnecting);\n this.startWebSocketConnectionAttempt();\n };\n\n websocket.addEventListener(\"close\", () => {\n if (websocket !== this.websocket) {\n console.warn(\"Ignoring websocket close event because it is no longer current\");\n return;\n }\n onWebsocketClose();\n });\n websocket.addEventListener(\"error\", (e) => {\n if (websocket !== this.websocket) {\n console.log(\"Ignoring websocket error event because it is no longer current\");\n return;\n }\n console.error(\"NetworkedDOMWebsocket error\", e);\n onWebsocketClose();\n });\n\n this.setStatus(NetworkedDOMWebsocketStatus.ConnectionOpen);\n resolve(websocket);\n });\n websocket.addEventListener(\"error\", (e) => {\n clearTimeout(timeoutId);\n reject(e);\n });\n });\n }\n\n private async waitBackoffTime(): Promise<void> {\n console.warn(`Websocket connection to '${this.url}' failed: retrying in ${this.backoffTime}ms`);\n await new Promise((resolve) => setTimeout(resolve, this.backoffTime));\n this.backoffTime = Math.min(\n // Introduce a small amount of randomness to prevent clients from retrying in lockstep\n this.backoffTime * (1.5 + Math.random() * 0.5),\n maximumBackoffTimeMilliseconds,\n );\n }\n\n private async startWebSocketConnectionAttempt() {\n if (this.stopped) {\n return;\n }\n while (true) {\n if (this.stopped) {\n return;\n }\n try {\n await this.createWebsocketWithTimeout(maximumWebsocketConnectionTimeout);\n break;\n } catch (e) {\n console.error(\"Websocket connection failed\", e);\n // Connection failed, retry with backoff\n this.setStatus(NetworkedDOMWebsocketStatus.Reconnecting);\n await this.waitBackoffTime();\n }\n }\n }\n\n public stop() {\n this.stopped = true;\n if (this.websocket !== null) {\n this.websocket.close();\n this.websocket = null;\n }\n }\n\n public handleEvent(element: HTMLElement, event: CustomEvent<{ element: HTMLElement }>) {\n if (this.websocketAdapter) {\n this.websocketAdapter.handleEvent(element, event);\n }\n }\n}\n\nexport function isHTMLElement(node: unknown, rootNode: HTMLElement): node is HTMLElement {\n if (node instanceof HTMLElement) {\n return true;\n }\n if (!rootNode.ownerDocument.defaultView) {\n return false;\n }\n return node instanceof rootNode.ownerDocument.defaultView.HTMLElement;\n}\n\nexport function isText(node: unknown, rootNode: HTMLElement): node is Text {\n if (node instanceof Text) {\n return true;\n }\n if (!rootNode.ownerDocument.defaultView) {\n return false;\n }\n return node instanceof rootNode.ownerDocument.defaultView.Text;\n}\n", "import {\n NetworkedDOMV01AttributeChangedDiff,\n NetworkedDOMV01ChildrenChangedDiff,\n NetworkedDOMV01ClientMessage,\n NetworkedDOMV01NodeDescription,\n NetworkedDOMV01RemoteEvent,\n NetworkedDOMV01ServerMessage,\n NetworkedDOMV01SnapshotMessage,\n NetworkedDOMV01TextChangedDiff,\n} from \"@mml-io/networked-dom-protocol\";\n\nimport { DOMSanitizer } from \"./DOMSanitizer\";\nimport {\n isHTMLElement,\n isText,\n NetworkedDOMWebsocketAdapter,\n NetworkedDOMWebsocketOptions,\n} from \"./NetworkedDOMWebsocket\";\n\nexport class NetworkedDOMWebsocketV01Adapter implements NetworkedDOMWebsocketAdapter {\n private idToElement = new Map<number, Node>();\n private elementToId = new Map<Node, number>();\n private currentRoot: HTMLElement | null = null;\n\n constructor(\n private websocket: WebSocket,\n private parentElement: HTMLElement,\n private connectedCallback: () => void,\n private timeCallback?: (time: number) => void,\n private options: NetworkedDOMWebsocketOptions = {},\n ) {\n this.websocket.binaryType = \"arraybuffer\";\n }\n\n public handleEvent(element: HTMLElement, event: CustomEvent<{ element: HTMLElement }>) {\n const nodeId = this.elementToId.get(element);\n if (nodeId === undefined || nodeId === null) {\n throw new Error(\"Element not found\");\n }\n\n const detailWithoutElement: Partial<typeof event.detail> = {\n ...event.detail,\n };\n delete detailWithoutElement.element;\n\n const remoteEvent: NetworkedDOMV01RemoteEvent = {\n type: \"event\",\n nodeId,\n name: event.type,\n bubbles: event.bubbles,\n params: detailWithoutElement,\n };\n\n this.send(remoteEvent);\n }\n\n private send(fromClientMessage: NetworkedDOMV01ClientMessage) {\n this.websocket.send(JSON.stringify(fromClientMessage));\n }\n\n public clearContents(): boolean {\n this.idToElement.clear();\n this.elementToId.clear();\n if (this.currentRoot) {\n this.currentRoot.remove();\n this.currentRoot = null;\n return true;\n }\n return false;\n }\n\n receiveMessage(event: MessageEvent) {\n const messages = JSON.parse(event.data) as Array<NetworkedDOMV01ServerMessage>;\n for (const message of messages) {\n switch (message.type) {\n case \"error\":\n console.error(\"Error from server\", message);\n break;\n case \"warning\":\n console.warn(\"Warning from server\", message);\n break;\n default: {\n if (message.documentTime) {\n if (this.timeCallback) {\n this.timeCallback(message.documentTime);\n }\n }\n switch (message.type) {\n case \"snapshot\":\n this.handleSnapshot(message);\n this.connectedCallback();\n break;\n case \"attributeChange\":\n this.handleAttributeChange(message);\n break;\n case \"childrenChanged\":\n this.handleChildrenChanged(message);\n break;\n case \"textChanged\":\n this.handleTextChanged(message);\n break;\n case \"ping\":\n this.send({\n type: \"pong\",\n pong: message.ping,\n });\n break;\n default:\n console.warn(\"unknown message type\", message);\n break;\n }\n }\n }\n }\n }\n\n private handleTextChanged(message: NetworkedDOMV01TextChangedDiff) {\n const { nodeId, text } = message;\n\n if (nodeId === undefined || nodeId === null) {\n console.warn(\"No nodeId in textChanged message\");\n return;\n }\n const node = this.idToElement.get(nodeId);\n if (!node) {\n throw new Error(\"No node found for textChanged message\");\n }\n if (!isText(node, this.parentElement)) {\n throw new Error(\"Node for textChanged message is not a Text node\");\n }\n node.textContent = text;\n }\n\n private handleChildrenChanged(message: NetworkedDOMV01ChildrenChangedDiff) {\n const { nodeId, addedNodes, removedNodes, previousNodeId } = message;\n if (nodeId === undefined || nodeId === null) {\n console.warn(\"No nodeId in childrenChanged message\");\n return;\n }\n const parent = this.idToElement.get(nodeId);\n if (!parent) {\n throw new Error(\"No parent found for childrenChanged message\");\n }\n if (!parent.isConnected) {\n console.error(\"Parent is not connected\", parent);\n }\n if (!isHTMLElement(parent, this.parentElement)) {\n throw new Error(\"Parent is not an HTMLElement (that supports children)\");\n }\n let nextElement = null;\n let previousElement = null;\n if (previousNodeId) {\n previousElement = this.idToElement.get(previousNodeId);\n if (!previousElement) {\n throw new Error(\"No previous element found for childrenChanged message\");\n }\n nextElement = previousElement.nextSibling;\n }\n\n const elementsToAdd = [];\n for (const addedNode of addedNodes) {\n const childElement = this.handleNewElement(addedNode);\n if (childElement) {\n elementsToAdd.push(childElement);\n }\n }\n if (elementsToAdd.length) {\n if (previousElement) {\n if (nextElement) {\n // There is a previous and next element - insertBefore the next element\n const docFrag = new DocumentFragment();\n docFrag.append(...elementsToAdd);\n parent.insertBefore(docFrag, nextElement);\n } else {\n // No next element - must be the last children\n parent.append(...elementsToAdd);\n }\n } else {\n // No previous element - must be the first children\n parent.prepend(...elementsToAdd);\n }\n }\n for (const removedNode of removedNodes) {\n const childElement = this.idToElement.get(removedNode);\n if (!childElement) {\n throw new Error(`Child element not found: ${removedNode}`);\n }\n this.elementToId.delete(childElement);\n this.idToElement.delete(removedNode);\n parent.removeChild(childElement);\n if (isHTMLElement(childElement, this.parentElement)) {\n // If child is capable of supporting children then remove any that exist\n this.removeChildElementIds(childElement);\n }\n }\n }\n\n private removeChildElementIds(parent: HTMLElement) {\n for (let i = 0; i < parent.children.length; i++) {\n const child = parent.children[i];\n const childId = this.elementToId.get(child as HTMLElement);\n if (!childId) {\n console.error(\"Inner child of removed element had no id\", child);\n } else {\n this.elementToId.delete(child);\n this.idToElement.delete(childId);\n }\n this.removeChildElementIds(child as HTMLElement);\n }\n }\n\n private handleSnapshot(message: NetworkedDOMV01SnapshotMessage) {\n // This websocket is successfully connected. Reset the backoff time.\n if (this.currentRoot) {\n this.currentRoot.remove();\n this.currentRoot = null;\n this.elementToId.clear();\n this.idToElement.clear();\n }\n\n // create a tree of DOM elements\n // NOTE: the MElement constructors are not executed during this stage\n const element = this.handleNewElement(message.snapshot);\n if (!element) {\n throw new Error(\"Snapshot element not created\");\n }\n if (!isHTMLElement(element, this.parentElement)) {\n throw new Error(\"Snapshot element is not an HTMLElement\");\n }\n this.currentRoot = element;\n // appending to the tree causes MElements to be constructed\n this.parentElement.append(element);\n }\n\n private handleAttributeChange(message: NetworkedDOMV01AttributeChangedDiff) {\n const { nodeId, attribute, newValue } = message;\n if (nodeId === undefined || nodeId === null) {\n console.warn(\"No nodeId in attributeChange message\");\n return;\n }\n const element = this.idToElement.get(nodeId);\n if (element) {\n if (isHTMLElement(element, this.parentElement)) {\n if (newValue === null) {\n element.removeAttribute(attribute);\n } else {\n if (DOMSanitizer.shouldAcceptAttribute(attribute)) {\n element.setAttribute(attribute, newValue);\n }\n }\n } else {\n console.error(\"Element is not an HTMLElement and cannot support attributes\", element);\n }\n } else {\n console.error(\"No element found for attributeChange message\");\n }\n }\n\n private handleNewElement(message: NetworkedDOMV01NodeDescription): Node | null {\n if (message.type === \"text\") {\n const { nodeId, text } = message;\n const textNode = document.createTextNode(\"\");\n textNode.textContent = text;\n this.idToElement.set(nodeId, textNode);\n this.elementToId.set(textNode, nodeId);\n return textNode;\n }\n const { tag, nodeId, attributes, children, text } = message;\n if (nodeId === undefined || nodeId === null) {\n console.warn(\"No nodeId in handleNewElement message\", message);\n return null;\n }\n if (this.idToElement.has(nodeId)) {\n console.error(\n \"Received nodeId to add that is already present\",\n nodeId,\n this.idToElement.get(nodeId),\n );\n }\n if (tag === \"#text\") {\n const textNode = document.createTextNode(\"\");\n textNode.textContent = text || null;\n this.idToElement.set(nodeId, textNode);\n this.elementToId.set(textNode, nodeId);\n return textNode;\n }\n\n let element;\n try {\n let filteredTag = tag;\n if (this.options.tagPrefix) {\n if (!tag.toLowerCase().startsWith(this.options.tagPrefix.toLowerCase())) {\n filteredTag = this.options.replacementTagPrefix\n ? this.options.replacementTagPrefix + tag\n : `x-${tag}`;\n }\n }\n element = document.createElement(filteredTag);\n } catch (e) {\n console.error(`Error creating element: (${tag})`, e);\n element = document.createElement(\"x-div\");\n }\n this.idToElement.set(nodeId, element);\n this.elementToId.set(element, nodeId);\n for (const key in attributes) {\n if (DOMSanitizer.shouldAcceptAttribute(key)) {\n const value = attributes[key];\n element.setAttribute(key, value);\n }\n }\n if (children) {\n for (const child of children) {\n const childElement = this.handleNewElement(child);\n if (childElement) {\n element.append(childElement);\n }\n }\n }\n return element;\n }\n}\n", "import {\n BufferReader,\n BufferWriter,\n decodeServerMessages,\n encodeClientMessage,\n NetworkedDOMV02AttributesChangedDiff,\n NetworkedDOMV02ChangeHiddenFromDiff,\n NetworkedDOMV02ChildrenAddedDiff,\n NetworkedDOMV02ChildrenRemovedDiff,\n NetworkedDOMV02ClientMessage,\n NetworkedDOMV02DocumentTimeMessage,\n NetworkedDOMV02NodeDescription,\n NetworkedDOMV02PingMessage,\n NetworkedDOMV02RemoteEvent,\n NetworkedDOMV02ServerMessage,\n NetworkedDOMV02SnapshotMessage,\n NetworkedDOMV02TextChangedDiff,\n} from \"@mml-io/networked-dom-protocol\";\n\nimport { DOMSanitizer } from \"./DOMSanitizer\";\nimport {\n isHTMLElement,\n isText,\n NetworkedDOMWebsocketAdapter,\n NetworkedDOMWebsocketOptions,\n} from \"./NetworkedDOMWebsocket\";\n\n// This client uses a single connection id\nconst connectionId = 1;\n\n// If an element should not be visible to this client, it will be replaced with this tag and attributes will be stored ready to be applied if it is unhidden.\nconst hiddenTag = \"x-hidden\";\n\nexport class NetworkedDOMWebsocketV02Adapter implements NetworkedDOMWebsocketAdapter {\n private idToElement = new Map<number, Node>();\n private elementToId = new Map<Node, number>();\n private hiddenPlaceholderElements = new Map<\n number,\n {\n placeholder: Node;\n element: Node;\n }\n >();\n private currentRoot: HTMLElement | null = null;\n private batchMode = false;\n private batchMessages: Array<NetworkedDOMV02ServerMessage> = [];\n\n constructor(\n private websocket: WebSocket,\n private parentElement: HTMLElement,\n private connectedCallback: () => void,\n private timeCallback?: (time: number) => void,\n private options: NetworkedDOMWebsocketOptions = {},\n ) {\n this.websocket.binaryType = \"arraybuffer\";\n this.send({ type: \"connectUsers\", connectionIds: [connectionId] });\n }\n\n public handleEvent(element: HTMLElement, event: CustomEvent<{ element: HTMLElement }>) {\n const nodeId = this.elementToId.get(element);\n if (nodeId === undefined || nodeId === null) {\n console.error(\"Element not found for event\", { nodeId, element, event });\n return;\n }\n\n const detailWithoutElement: Partial<typeof event.detail> = {\n ...event.detail,\n };\n delete detailWithoutElement.element;\n\n const remoteEvent: NetworkedDOMV02RemoteEvent = {\n type: \"event\",\n nodeId,\n connectionId,\n name: event.type,\n bubbles: event.bubbles,\n params: detailWithoutElement,\n };\n\n this.send(remoteEvent);\n }\n\n private send(message: NetworkedDOMV02ClientMessage) {\n const writer = new BufferWriter(256);\n encodeClientMessage(message, writer);\n this.websocket.send(writer.getBuffer());\n }\n\n public clearContents(): boolean {\n this.idToElement.clear();\n this.elementToId.clear();\n if (this.currentRoot) {\n this.currentRoot.remove();\n this.currentRoot = null;\n return true;\n }\n return false;\n }\n\n public receiveMessage(event: MessageEvent) {\n const reader = new BufferReader(new Uint8Array(event.data));\n const messages = decodeServerMessages(reader);\n for (const message of messages) {\n if (message.type === \"batchStart\") {\n // Need to wait for batchEnd before applying messages\n this.batchMode = true;\n } else if (message.type === \"batchEnd\") {\n // Apply all messages\n this.batchMode = false;\n for (const message of this.batchMessages) {\n this.applyMessage(message);\n }\n this.batchMessages = [];\n } else {\n if (this.batchMode) {\n this.batchMessages.push(message);\n } else {\n this.applyMessage(message);\n }\n }\n }\n }\n\n private applyMessage(message: NetworkedDOMV02ServerMessage) {\n switch (message.type) {\n case \"error\":\n console.error(\"Error from server\", message);\n break;\n case \"warning\":\n console.warn(\"Warning from server\", message);\n break;\n case \"snapshot\":\n this.handleSnapshot(message);\n this.connectedCallback();\n break;\n case \"attributesChanged\":\n this.handleAttributeChange(message);\n break;\n case \"documentTime\":\n this.handleDocumentTime(message);\n break;\n case \"childrenAdded\":\n this.handleChildrenAdded(message);\n break;\n case \"changeHiddenFrom\":\n this.handleChangeHiddenFrom(message);\n break;\n case \"changeVisibleTo\":\n // no-op for end user clients\n break;\n case \"childrenRemoved\":\n this.handleChildrenRemoved(message);\n break;\n case \"textChanged\":\n this.handleTextChanged(message);\n break;\n case \"ping\":\n this.handlePing(message);\n break;\n default:\n console.warn(\"unknown message type\", message);\n break;\n }\n }\n\n private handleTextChanged(message: NetworkedDOMV02TextChangedDiff) {\n const { nodeId, text } = message;\n\n if (nodeId === undefined || nodeId === null) {\n console.warn(\"No nodeId in textChanged message\");\n return;\n }\n const node = this.idToElement.get(nodeId);\n if (!node) {\n throw new Error(\"No node found for textChanged message\");\n }\n if (!isText(node, this.parentElement)) {\n throw new Error(\"Node for textChanged message is not a Text node\");\n }\n node.textContent = text;\n }\n\n private handleChangeHiddenFrom(message: NetworkedDOMV02ChangeHiddenFromDiff) {\n const { nodeId, addHiddenFrom, removeHiddenFrom } = message;\n const node = this.idToElement.get(nodeId);\n const hiddenElement = this.hiddenPlaceholderElements.get(nodeId);\n if (addHiddenFrom.length > 0 && addHiddenFrom.indexOf(connectionId) !== -1) {\n // This element is being hidden\n if (hiddenElement) {\n // This element is already hidden\n return;\n }\n if (!node) {\n throw new Error(\"No node found for changeHiddenFrom message\");\n }\n const parent = node.parentElement;\n if (!parent) {\n throw new Error(\"Node has no parent\");\n }\n const placeholder = document.createElement(hiddenTag);\n parent.replaceChild(placeholder, node);\n this.hiddenPlaceholderElements.set(nodeId, { placeholder, element: node });\n } else if (removeHiddenFrom.length > 0 && removeHiddenFrom.indexOf(connectionId) !== -1) {\n // This element is being unhidden\n if (!hiddenElement) {\n // This element is not hidden\n return;\n }\n const { placeholder, element } = hiddenElement;\n const parent = placeholder.parentElement;\n if (!parent) {\n throw new Error(\"Placeholder has no parent\");\n }\n parent.replaceChild(element, placeholder);\n this.hiddenPlaceholderElements.delete(nodeId);\n }\n }\n\n private handleChildrenAdded(message: NetworkedDOMV02ChildrenAddedDiff) {\n const { nodeId, addedNodes, previousNodeId } = message;\n if (nodeId === undefined || nodeId === null) {\n console.warn(\"No nodeId in childrenChanged message\");\n return;\n }\n let parent = this.idToElement.get(nodeId);\n if (!parent) {\n throw new Error(\"No parent found for childrenChanged message\");\n }\n\n const hiddenParent = this.hiddenPlaceholderElements.get(nodeId);\n if (hiddenParent) {\n // This element is hidden - add the children to the hidden element (not the placeholder)\n parent = hiddenParent.element;\n } else {\n if (!parent.isConnected) {\n console.error(\"Parent is not connected\", parent);\n }\n }\n if (!isHTMLElement(parent, this.parentElement)) {\n throw new Error(\"Parent is not an HTMLElement (that supports children)\");\n }\n let nextElement = null;\n let previousElement = null;\n if (previousNodeId) {\n previousElement = this.idToElement.get(previousNodeId);\n if (!previousElement) {\n throw new Error(\"No previous element found for childrenChanged message\");\n }\n nextElement = previousElement.nextSibling;\n }\n\n const elementsToAdd = [];\n for (const addedNode of addedNodes) {\n const childElement = this.handleNewElement(addedNode);\n if (childElement) {\n elementsToAdd.push(childElement);\n }\n }\n if (elementsToAdd.length) {\n if (previousElement) {\n if (nextElement) {\n // There is a previous and next element - insertBefore the next element\n const docFrag = new DocumentFragment();\n docFrag.append(...elementsToAdd);\n parent.insertBefore(docFrag, nextElement);\n } else {\n // No next element - must be the last children\n parent.append(...elementsToAdd);\n }\n } else {\n // No previous element - must be the first children\n parent.prepend(...elementsToAdd);\n }\n }\n }\n\n private handleChildrenRemoved(message: NetworkedDOMV02ChildrenRemovedDiff) {\n const { nodeId, removedNodes } = message;\n if (nodeId === undefined || nodeId === null) {\n console.warn(\"No nodeId in childrenChanged message\");\n return;\n }\n const parent = this.idToElement.get(nodeId);\n if (!parent) {\n throw new Error(\"No parent found for childrenChanged message\");\n }\n if (!parent.isConnected) {\n console.error(\"Parent is not connected\", parent);\n }\n if (!isHTMLElement(parent, this.parentElement)) {\n throw new Error(\"Parent is not an HTMLElement (that supports children)\");\n }\n\n for (const removedNode of removedNodes) {\n const childElement = this.idToElement.get(removedNode);\n if (!childElement) {\n throw new Error(`Child element not found: ${removedNode}`);\n }\n this.elementToId.delete(childElement);\n this.idToElement.delete(removedNode);\n this.hiddenPlaceholderElements.delete(removedNode);\n parent.removeChild(childElement);\n if (isHTMLElement(childElement, this.parentElement)) {\n // If child is capable of supporting children then remove any that exist\n this.removeChildElementIds(childElement);\n }\n }\n }\n\n private removeChildElementIds(parent: HTMLElement) {\n for (let i = 0; i < parent.children.length; i++) {\n const child = parent.children[i];\n const childId = this.elementToId.get(child as HTMLElement);\n if (!childId) {\n console.error(\"Inner child of removed element had no id\", child);\n } else {\n this.elementToId.delete(child);\n this.idToElement.delete(childId);\n this.hiddenPlaceholderElements.delete(childId);\n }\n this.removeChildElementIds(child as HTMLElement);\n }\n }\n\n private handleSnapshot(message: NetworkedDOMV02SnapshotMessage) {\n // This websocket is successfully connected. Reset the backoff time.\n if (this.currentRoot) {\n this.currentRoot.remove();\n this.currentRoot = null;\n this.elementToId.clear();\n this.idToElement.clear();\n }\n\n this.timeCallback?.(message.documentTime);\n\n // create a tree of DOM elements\n // NOTE: the MElement constructors are not executed during this stage\n const element = this.handleNewElement(message.snapshot);\n if (!element) {\n throw new Error(\"Snapshot element not created\");\n }\n if (!isHTMLElement(element, this.parentElement)) {\n throw new Error(\"Snapshot element is not an HTMLElement\");\n }\n this.currentRoot = element;\n // appending to the tree causes MElements to be constructed\n this.parentElement.append(element);\n }\n\n private handleDocumentTime(message: NetworkedDOMV02DocumentTimeMessage) {\n this.timeCallback?.(message.documentTime);\n }\n\n private handleAttributeChange(message: NetworkedDOMV02AttributesChangedDiff) {\n const { nodeId, attributes } = message;\n if (nodeId === undefined || nodeId === null) {\n console.warn(\"No nodeId in attributeChange message\");\n return;\n }\n let element = this.idToElement.get(nodeId);\n const hiddenElement = this.hiddenPlaceholderElements.get(nodeId);\n if (hiddenElement) {\n // This element is hidden - apply the attributes to the hidden element\n element = hiddenElement.element;\n }\n if (element) {\n if (isHTMLElement(element, this.parentElement)) {\n for (const [key, newValue] of attributes) {\n if (newValue === null) {\n element.removeAttribute(key);\n } else {\n if (DOMSanitizer.shouldAcceptAttribute(key)) {\n element.setAttribute(key, newValue);\n }\n }\n }\n } else {\n console.error(\"Element is not an HTMLElement and cannot support attributes\", element);\n }\n } else {\n console.error(\"No element found for attributeChange message\");\n }\n }\n\n private handleNewElement(message: NetworkedDOMV02NodeDescription): Node | null {\n if (message.type === \"text\") {\n const { nodeId, text } = message;\n const textNode = document.createTextNode(\"\");\n textNode.textContent = text;\n this.idToElement.set(nodeId, textNode);\n this.elementToId.set(textNode, nodeId);\n return textNode;\n }\n const { tag, nodeId, attributes, children, text, hiddenFrom } = message;\n if (this.idToElement.has(nodeId)) {\n console.error(\n \"Received nodeId to add that is already present\",\n nodeId,\n this.idToElement.get(nodeId),\n );\n return null;\n }\n\n if (tag === \"#text\") {\n const textNode = document.createTextNode(\"\");\n textNode.textContent = text || null;\n this.idToElement.set(nodeId, textNode);\n this.elementToId.set(textNode, nodeId);\n return textNode;\n }\n\n let element;\n try {\n let filteredTag = tag;\n if (this.options.tagPrefix) {\n if (!tag.toLowerCase().startsWith(this.options.tagPrefix.toLowerCase())) {\n filteredTag = this.options.replacementTagPrefix\n ? this.options.replacementTagPrefix + tag\n : `x-${tag}`;\n }\n }\n element = document.createElement(filteredTag);\n } catch (e) {\n console.error(`Error creating element: (${tag})`, e);\n element = document.createElement(\"x-div\");\n }\n for (const [key, value] of attributes) {\n if (value !== null) {\n if (DOMSanitizer.shouldAcceptAttribute(key)) {\n element.setAttribute(key, value);\n }\n }\n }\n if (children) {\n for (const child of children) {\n const childElement = this.handleNewElement(child);\n if (childElement) {\n element.append(childElement);\n }\n }\n }\n\n if (hiddenFrom && hiddenFrom.length > 0 && hiddenFrom.indexOf(connectionId) !== -1) {\n // This element is hidden - create a placeholder that will be in the DOM to maintain structure, but keep the underlying element hidden\n const placeholder = document.createElement(hiddenTag);\n this.idToElement.set(nodeId, placeholder);\n this.elementToId.set(placeholder, nodeId);\n this.hiddenPlaceholderElements.set(nodeId, { placeholder, element });\n return placeholder;\n } else {\n this.idToElement.set(nodeId, element);\n this.elementToId.set(element, nodeId);\n return element;\n }\n }\n\n private handlePing(message: NetworkedDOMV02PingMessage) {\n this.timeCallback?.(message.documentTime);\n this.send({\n type: \"pong\",\n pong: message.ping,\n });\n }\n}\n", "import { NetworkedDOMWebsocket } from \"@mml-io/networked-dom-web\";\n\nconst thisScript = document.currentScript as HTMLScriptElement;\nconst scriptUrl = new URL(thisScript.src);\n\n(function () {\n const url = scriptUrl.searchParams.get(\"url\");\n if (!url) {\n console.error(\"url not set\");\n return;\n }\n window.addEventListener(\"load\", () => {\n let overriddenHandler: ((element: HTMLElement, event: CustomEvent) => void) | null = null;\n const eventHandler = (element: HTMLElement, event: CustomEvent) => {\n if (!overriddenHandler) {\n throw new Error(\"overriddenHandler not set\");\n }\n overriddenHandler(element, event);\n };\n const remoteDocumentHolder = document.createElement(\"div\");\n document.body.append(remoteDocumentHolder);\n\n remoteDocumentHolder.addEventListener(\"click\", (event: Event) => {\n eventHandler(event.target as HTMLElement, event as CustomEvent);\n return false;\n });\n\n const websocket = new NetworkedDOMWebsocket(\n url,\n NetworkedDOMWebsocket.createWebSocket,\n remoteDocumentHolder,\n );\n overriddenHandler = (element: HTMLElement, event: CustomEvent) => {\n websocket.handleEvent(element, event);\n };\n });\n})();\n"],
5
- "mappings": "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",
3
+ "sources": ["../../networked-dom-protocol/src/networked-dom-v0.1/constants.ts", "../../networked-dom-protocol/src/networked-dom-v0.2/BufferReader.ts", "../../networked-dom-protocol/src/networked-dom-v0.2/BufferWriter.ts", "../../networked-dom-protocol/src/networked-dom-v0.2/common-structs/attributes.ts", "../../networked-dom-protocol/src/networked-dom-v0.2/common-structs/nodeDescription.ts", "../../networked-dom-protocol/src/networked-dom-v0.2/constants.ts", "../../networked-dom-protocol/src/networked-dom-v0.2/featureDetection.ts", "../../networked-dom-protocol/src/networked-dom-v0.2/messageTypes.ts", "../../networked-dom-protocol/src/networked-dom-v0.2/messages/from-client/connectUsers.ts", "../../networked-dom-protocol/src/networked-dom-v0.2/messages/from-client/disconnectUsers.ts", "../../networked-dom-protocol/src/networked-dom-v0.2/messages/from-client/event.ts", "../../networked-dom-protocol/src/networked-dom-v0.2/messages/from-client/pong.ts", "../../networked-dom-protocol/src/networked-dom-v0.2/decodeClientMessages.ts", "../../networked-dom-protocol/src/networked-dom-v0.2/messages/from-server/attributesChanged.ts", "../../networked-dom-protocol/src/networked-dom-v0.2/messages/from-server/batchEnd.ts", "../../networked-dom-protocol/src/networked-dom-v0.2/messages/from-server/batchStart.ts", "../../networked-dom-protocol/src/networked-dom-v0.2/messages/from-server/changeHiddenFrom.ts", "../../networked-dom-protocol/src/networked-dom-v0.2/messages/from-server/changeVisibleTo.ts", "../../networked-dom-protocol/src/networked-dom-v0.2/messages/from-server/childrenAdded.ts", "../../networked-dom-protocol/src/networked-dom-v0.2/messages/from-server/childrenRemoved.ts", "../../networked-dom-protocol/src/networked-dom-v0.2/messages/from-server/documentTime.ts", "../../networked-dom-protocol/src/networked-dom-v0.2/messages/from-server/error.ts", "../../networked-dom-protocol/src/networked-dom-v0.2/messages/from-server/ping.ts", "../../networked-dom-protocol/src/networked-dom-v0.2/messages/from-server/snapshot.ts", "../../networked-dom-protocol/src/networked-dom-v0.2/messages/from-server/textChanged.ts", "../../networked-dom-protocol/src/networked-dom-v0.2/messages/from-server/warning.ts", "../../networked-dom-protocol/src/networked-dom-v0.2/decodeServerMessages.ts", "../../networked-dom-protocol/src/networked-dom-v0.2/encodeClientMessage.ts", "../../networked-dom-protocol/src/networked-dom-v0.2/encodeServerMessage.ts", "../../networked-dom-web/src/DOMSanitizer.ts", "../../networked-dom-web/src/NetworkedDOMWebsocket.ts", "../../networked-dom-web/src/ElementUtils.ts", "../../networked-dom-web/src/NetworkedDOMWebsocketV01Adapter.ts", "../../networked-dom-web/src/NetworkedDOMWebsocketV02Adapter.ts", "../src/index.ts"],
4
+ "sourcesContent": ["export const networkedDOMProtocolSubProtocol_v0_1 = \"networked-dom-v0.1\";\n", "const textDecoder = new TextDecoder();\n\nexport class BufferReader {\n private buffer: Uint8Array;\n private offset: number;\n\n constructor(buffer: Uint8Array) {\n this.buffer = buffer;\n this.offset = 0;\n }\n\n public readUInt8(): number {\n return this.buffer[this.offset++];\n }\n\n public readBoolean(): boolean {\n return this.readUInt8() === 1;\n }\n\n public readUVarint(signed = false): number {\n let lo = 0;\n let hi = 0;\n let i = 0;\n for (; i < 4; ++i) {\n lo = (lo | ((this.buffer[this.offset] & 127) << (i * 7))) >>> 0;\n if (this.buffer[this.offset++] < 128) {\n return signed ? loAndHiAsSigned(lo, hi) : loAndHiAsUnsigned(lo, hi);\n }\n }\n lo = (lo | ((this.buffer[this.offset] & 127) << 28)) >>> 0;\n hi = (hi | ((this.buffer[this.offset] & 127) >> 4)) >>> 0;\n if (this.buffer[this.offset++] < 128) {\n return signed ? loAndHiAsSigned(lo, hi) : loAndHiAsUnsigned(lo, hi);\n }\n i = 0;\n for (; i < 5; ++i) {\n hi = (hi | ((this.buffer[this.offset] & 127) << (i * 7 + 3))) >>> 0;\n if (this.buffer[this.offset++] < 128) {\n return signed ? loAndHiAsSigned(lo, hi) : loAndHiAsUnsigned(lo, hi);\n }\n }\n\n throw Error(\"invalid varint encoding\");\n }\n\n public readUVarintPrefixedString(): string {\n const readLength = this.readUVarint();\n\n let string = \"\";\n let hasNonAscii = false;\n for (let i = 0; i < readLength; i++) {\n const charValue = this.buffer[this.offset + i];\n if (charValue < 0x80) {\n string += String.fromCharCode(charValue);\n } else {\n hasNonAscii = true;\n break;\n }\n }\n if (!hasNonAscii) {\n this.offset += readLength;\n return string;\n }\n\n // Slow path - decode the string using TextDecoder\n const result = textDecoder.decode(this.buffer.subarray(this.offset, this.offset + readLength));\n this.offset += readLength;\n return result;\n }\n\n // returns the string and a boolean indicating if the string was negative length\n public readVarintPrefixedString(): [string, boolean] {\n const length = this.readVarint();\n const negativeLength = length < 0;\n const readLength = negativeLength ? -length : length;\n\n let string = \"\";\n let hasNonAscii = false;\n for (let i = 0; i < readLength; i++) {\n const charValue = this.buffer[this.offset + i];\n if (charValue < 0x80) {\n string += String.fromCharCode(charValue);\n } else {\n hasNonAscii = true;\n break;\n }\n }\n if (!hasNonAscii) {\n this.offset += readLength;\n return [string, negativeLength];\n }\n\n // Slow path - decode the string using TextDecoder\n const result = textDecoder.decode(this.buffer.subarray(this.offset, this.offset + readLength));\n this.offset += readLength;\n return [result, negativeLength];\n }\n\n public readVarint(): number {\n return this.readUVarint(true);\n }\n\n public isEnd() {\n return this.offset >= this.buffer.length;\n }\n}\n\nfunction loAndHiAsSigned(lo: number, hi: number) {\n const value = lo + hi * 4294967296;\n if (value & 1) {\n return -(value + 1) / 2;\n }\n return value / 2;\n}\n\nfunction loAndHiAsUnsigned(lo: number, hi: number) {\n return lo + hi * 4294967296;\n}\n", "const textEncoder = new TextEncoder();\n\nexport class BufferWriter {\n private buffer: Uint8Array;\n private offset: number;\n\n constructor(initialLength: number) {\n this.buffer = new Uint8Array(initialLength);\n this.offset = 0;\n }\n\n // Write an unsigned 8-bit integer\n public writeUint8(value: number): void {\n this.ensureCapacity(1);\n this.buffer[this.offset] = value & 0xff;\n this.offset += 1;\n }\n\n public writeBoolean(bool: boolean) {\n this.writeUint8(bool ? 1 : 0);\n }\n\n // Write an array of bytes\n public writeBytes(bytes: Uint8Array): void {\n this.ensureCapacity(bytes.byteLength);\n this.buffer.set(bytes, this.offset);\n this.offset += bytes.byteLength;\n }\n\n // Get the written bytes as a Uint8Array\n public getBuffer(): Uint8Array {\n return this.buffer.subarray(0, this.offset);\n }\n\n public getWrittenLength(): number {\n return this.offset;\n }\n\n // Ensure there is enough capacity in the buffer\n private ensureCapacity(neededSpace: number): void {\n while (this.offset + neededSpace > this.buffer.length) {\n this.expandBuffer();\n }\n }\n\n // Expand the buffer by doubling its current length\n private expandBuffer(): void {\n const newBuffer = new Uint8Array(this.buffer.length * 2);\n newBuffer.set(this.buffer);\n this.buffer = newBuffer;\n }\n\n public writeUVarint(x: number) {\n if (x <= 268435455) {\n // Simple case that can be handled without hi and lo\n this.ensureCapacity(4);\n while (x >= 0x80) {\n this.buffer[this.offset] = (x & 0x7f) | 0x80; // Extract least significant 7 bits and set continuation bit\n this.offset++;\n x >>>= 7; // Use unsigned shift here\n }\n this.buffer[this.offset] = x & 0x7f; // No need for 0xff here since we're limiting it to 7 bits\n this.offset++;\n return;\n }\n this.ensureCapacity(10);\n\n let lo = 0;\n let hi = 0;\n if (x !== 0) {\n lo = x >>> 0;\n hi = ((x - lo) / 4294967296) >>> 0;\n }\n\n while (hi) {\n this.buffer[this.offset++] = (lo & 127) | 128;\n lo = ((lo >>> 7) | (hi << 25)) >>> 0;\n hi >>>= 7;\n }\n while (lo > 127) {\n this.buffer[this.offset++] = (lo & 127) | 128;\n lo = lo >>> 7;\n }\n this.buffer[this.offset++] = lo;\n }\n\n public writeVarint(x: number) {\n if (x >= 0) {\n this.writeUVarint(x * 2);\n } else {\n this.writeUVarint(-x * 2 - 1);\n }\n }\n\n public writeLengthPrefixedString(value: string, varint = false, negativeLength = false) {\n /*\n Try fast case first - no non-ascii characters and byte length is string length.\n\n Even if this case fails (non-ascii character found) the data will always be\n shorter so it can be overwritten\n */\n const originalOffset = this.offset; // store this in case we need to overwrite from here\n // Just write the length of the string (not the known encoded length)\n if (varint) {\n this.writeVarint(negativeLength ? -value.length : value.length);\n } else {\n this.writeUVarint(value.length);\n }\n this.ensureCapacity(value.length); // Ensure we have enough space for the string\n let nonAscii = false;\n for (let i = 0; i < value.length; i++) {\n const charCode = value.charCodeAt(i);\n if (charCode > 0x7f) {\n nonAscii = true;\n break;\n }\n this.buffer[this.offset++] = charCode;\n }\n\n if (!nonAscii) {\n return;\n }\n\n /*\n If we have non-ascii characters, we need to encode the string respecting\n utf-8 and overwrite the buffer from the original offset\n */\n this.offset = originalOffset; // overwrite the length\n let encodedLength = value.length; // This will be overwritten once we know the actual length\n this.ensureCapacity(encodedLength); // This will be at least the required length, but it gives the chance of initially creating a large enough buffer\n while (true) {\n this.offset = originalOffset;\n if (varint) {\n this.writeVarint(negativeLength ? -encodedLength : encodedLength);\n } else {\n this.writeUVarint(encodedLength);\n }\n const offsetAfterVarint = this.offset;\n const varintLength = offsetAfterVarint - originalOffset;\n\n const writeBuffer = new Uint8Array(this.buffer.buffer, this.offset);\n const { read, written } = textEncoder.encodeInto(value, writeBuffer);\n if (read !== value.length) {\n // Need more space and try again\n this.expandBuffer();\n continue;\n }\n if (written !== encodedLength) {\n encodedLength = written;\n // We need to overwrite the varint with the correct length\n this.offset = originalOffset;\n if (varint) {\n this.writeVarint(negativeLength ? -encodedLength : encodedLength);\n } else {\n this.writeUVarint(encodedLength);\n }\n const newOffsetAfterVarint = this.offset;\n const actualVarintLength = newOffsetAfterVarint - originalOffset;\n if (actualVarintLength !== varintLength) {\n // The varint length changed and it has overwritten the string\n // We need to write the string again\n continue;\n } else {\n // The varint length is the same so the string is intact\n }\n }\n // String written successfully - update the offset\n this.offset += written;\n return;\n }\n }\n}\n", "import { BufferReader } from \"../BufferReader\";\nimport { BufferWriter } from \"../BufferWriter\";\n\nexport function encodeAttribute(writer: BufferWriter, key: string, value: string | null) {\n if (value === null) {\n writer.writeLengthPrefixedString(key, true, true);\n } else {\n writer.writeLengthPrefixedString(key, true, false);\n writer.writeLengthPrefixedString(value);\n }\n}\n\nexport function encodeAttributes(writer: BufferWriter, attributes: Array<[string, string | null]>) {\n writer.writeUVarint(attributes.length);\n\n for (let i = 0; i < attributes.length; i++) {\n encodeAttribute(writer, attributes[i][0], attributes[i][1]);\n }\n}\n\nexport function decodeAttributes(buffer: BufferReader): Array<[string, string | null]> {\n const attributesLength = buffer.readUVarint();\n const attributes: Array<[string, string | null]> = [];\n for (let i = 0; i < attributesLength; i++) {\n const [key, negativeLength] = buffer.readVarintPrefixedString();\n if (negativeLength) {\n attributes.push([key, null]);\n continue;\n }\n const value = buffer.readUVarintPrefixedString();\n attributes.push([key, value]);\n }\n return attributes;\n}\n", "import { BufferReader } from \"../BufferReader\";\nimport { BufferWriter } from \"../BufferWriter\";\nimport { decodeAttributes, encodeAttributes } from \"./attributes\";\n\nexport type NetworkedDOMV02TextNodeDescription = {\n type: \"text\";\n nodeId: number;\n text: string;\n};\n\nexport type NetworkedDOMV02ElementNodeDescription = {\n type: \"element\";\n nodeId: number;\n tag: string;\n attributes: Array<[string, string | null]>;\n children: Array<NetworkedDOMV02NodeDescription>;\n visibleTo?: Array<number>;\n hiddenFrom?: Array<number>;\n text?: string;\n};\n\nexport type NetworkedDOMV02NodeDescription =\n | NetworkedDOMV02ElementNodeDescription\n | NetworkedDOMV02TextNodeDescription;\n\nexport function encodeNodeDescription(\n writer: BufferWriter,\n nodeDescription: NetworkedDOMV02NodeDescription,\n): void {\n writer.writeUVarint(nodeDescription.nodeId);\n\n if (nodeDescription.type === \"text\") {\n writer.writeLengthPrefixedString(\"\"); // Empty tag indicates text node\n writer.writeLengthPrefixedString(nodeDescription.text);\n return;\n }\n\n writer.writeLengthPrefixedString(nodeDescription.tag);\n\n encodeAttributes(writer, nodeDescription.attributes);\n\n if (!nodeDescription.visibleTo) {\n writer.writeUVarint(0);\n } else {\n writer.writeUVarint(nodeDescription.visibleTo.length);\n for (let i = 0; i < nodeDescription.visibleTo.length; i++) {\n writer.writeUVarint(nodeDescription.visibleTo[i]);\n }\n }\n\n if (!nodeDescription.hiddenFrom) {\n writer.writeUVarint(0);\n } else {\n writer.writeUVarint(nodeDescription.hiddenFrom.length);\n for (let i = 0; i < nodeDescription.hiddenFrom.length; i++) {\n writer.writeUVarint(nodeDescription.hiddenFrom[i]);\n }\n }\n\n writer.writeUVarint(nodeDescription.children.length);\n for (let i = 0; i < nodeDescription.children.length; i++) {\n encodeNodeDescription(writer, nodeDescription.children[i]);\n }\n}\n\nexport function decodeNodeDescription(buffer: BufferReader): NetworkedDOMV02NodeDescription {\n const nodeId = buffer.readUVarint();\n const tag = buffer.readUVarintPrefixedString();\n if (tag === \"\") {\n // Text node\n const text = buffer.readUVarintPrefixedString();\n return { type: \"text\", nodeId, text };\n }\n\n const attributes = decodeAttributes(buffer);\n\n const visibleToLength = buffer.readUVarint();\n let visibleTo: number[] | undefined;\n if (visibleToLength !== 0) {\n visibleTo = [];\n for (let i = 0; i < visibleToLength; i++) {\n visibleTo.push(buffer.readUVarint());\n }\n }\n\n const hiddenFromLength = buffer.readUVarint();\n let hiddenFrom: number[] | undefined;\n if (hiddenFromLength !== 0) {\n hiddenFrom = [];\n for (let i = 0; i < hiddenFromLength; i++) {\n hiddenFrom.push(buffer.readUVarint());\n }\n }\n\n const childrenLength = buffer.readUVarint();\n const children: NetworkedDOMV02NodeDescription[] = [];\n for (let i = 0; i < childrenLength; i++) {\n children.push(decodeNodeDescription(buffer));\n }\n\n const node: NetworkedDOMV02ElementNodeDescription = {\n type: \"element\",\n nodeId,\n tag,\n attributes,\n children,\n };\n\n if (visibleTo) {\n node.visibleTo = visibleTo;\n }\n if (hiddenFrom) {\n node.hiddenFrom = hiddenFrom;\n }\n\n return node;\n}\n", "export const networkedDOMProtocolSubProtocol_v0_2 = \"networked-dom-v0.2\";\nexport const networkedDOMProtocolSubProtocol_v0_2_1 = \"networked-dom-v0.2.1\";\n\n// In priority order, from most preferred to least preferred\nexport const networkedDOMProtocolSubProtocol_v0_2_SubVersionsList = [\n networkedDOMProtocolSubProtocol_v0_2_1,\n networkedDOMProtocolSubProtocol_v0_2,\n] as const;\n\nexport type networkedDOMProtocolSubProtocol_v0_2_Subversion =\n (typeof networkedDOMProtocolSubProtocol_v0_2_SubVersionsList)[number];\n\nexport type networkedDOMProtocolSubProtocol_v0_2_SubversionNumber = 0 | 1;\n\nconst protocolSubVersionMap: Record<\n networkedDOMProtocolSubProtocol_v0_2_Subversion,\n networkedDOMProtocolSubProtocol_v0_2_SubversionNumber\n> = {\n [networkedDOMProtocolSubProtocol_v0_2]: 0,\n [networkedDOMProtocolSubProtocol_v0_2_1]: 1,\n};\n\nexport function getNetworkedDOMProtocolSubProtocol_v0_2Subversion(\n protocol: networkedDOMProtocolSubProtocol_v0_2_Subversion,\n): networkedDOMProtocolSubProtocol_v0_2_SubversionNumber | null {\n return protocolSubVersionMap[protocol] ?? null;\n}\n\nexport function getNetworkedDOMProtocolSubProtocol_v0_2SubversionOrThrow(\n protocol: networkedDOMProtocolSubProtocol_v0_2_Subversion,\n): networkedDOMProtocolSubProtocol_v0_2_SubversionNumber {\n const subversion = getNetworkedDOMProtocolSubProtocol_v0_2Subversion(protocol);\n if (subversion === null) {\n throw new Error(`Unrecognized networked-dom-v0.2 protocol subversion: ${protocol}`);\n }\n return subversion;\n}\n\nexport function isNetworkedDOMProtocolSubProtocol_v0_2(\n protocol: string,\n): protocol is (typeof networkedDOMProtocolSubProtocol_v0_2_SubVersionsList)[number] {\n return networkedDOMProtocolSubProtocol_v0_2_SubVersionsList.includes(protocol as any);\n}\n", "import { networkedDOMProtocolSubProtocol_v0_2_SubversionNumber } from \"./constants\";\n\n// Whether the given protocol subversion supports the `connectionTokens` field in the `connectUsers` message\nexport function protocolSubversionHasConnectionTokens(\n protocolSubversion: networkedDOMProtocolSubProtocol_v0_2_SubversionNumber,\n) {\n return protocolSubversion >= 1;\n}\n", "// Server -> Client\nexport const SnapshotMessageType = 1;\nexport const BatchStartMessageType = 2;\nexport const DocumentTimeMessageType = 3;\nexport const ChildrenAddedMessageType = 4;\nexport const ChildrenRemovedMessageType = 5;\nexport const AttributesChangedMessageType = 6;\nexport const ChangeVisibleToMessageType = 7;\nexport const ChangeHiddenFromMessageType = 8;\nexport const TextChangedMessageType = 9;\nexport const BatchEndMessageType = 10;\nexport const PingMessageType = 11;\nexport const WarningMessageType = 12;\nexport const ErrorMessageType = 13;\n\n// Client -> Server\nexport const ConnectUsersMessageType = 14;\nexport const DisconnectUsersMessageType = 15;\nexport const EventMessageType = 16;\nexport const PongMessageType = 17;\n", "import { BufferReader } from \"../../BufferReader\";\nimport { BufferWriter } from \"../../BufferWriter\";\nimport { networkedDOMProtocolSubProtocol_v0_2_SubversionNumber } from \"../../constants\";\nimport { protocolSubversionHasConnectionTokens } from \"../../featureDetection\";\nimport { ConnectUsersMessageType } from \"../../messageTypes\";\n\nexport type NetworkedDOMV02ConnectUsersMessage = {\n type: \"connectUsers\";\n connectionIds: Array<number>;\n // Enabled in networked-dom-v0.2.1 and above\n connectionTokens: Array<string | null>; // Optional tokens for each connection ID. On decoding empty string will be interpreted as null\n};\n\nexport function encodeConnectUsers(\n connectUsersMessage: NetworkedDOMV02ConnectUsersMessage,\n writer: BufferWriter,\n protocolSubversion: networkedDOMProtocolSubProtocol_v0_2_SubversionNumber,\n) {\n const connectionIdsLength = connectUsersMessage.connectionIds.length;\n writer.writeUint8(ConnectUsersMessageType);\n writer.writeUVarint(connectionIdsLength);\n for (let i = 0; i < connectionIdsLength; i++) {\n writer.writeUVarint(connectUsersMessage.connectionIds[i]);\n }\n if (protocolSubversionHasConnectionTokens(protocolSubversion)) {\n if (connectUsersMessage.connectionTokens.length !== connectionIdsLength) {\n throw new Error(\n `connectionTokens length (${connectUsersMessage.connectionTokens.length}) does not match connectionIds length (${connectionIdsLength})`,\n );\n }\n for (let i = 0; i < connectionIdsLength; i++) {\n const token = connectUsersMessage.connectionTokens[i];\n if (token === null || token === undefined) {\n writer.writeUVarint(0); // Length 0 means no token\n } else {\n writer.writeLengthPrefixedString(token);\n }\n }\n }\n}\n\n// Assumes that the first byte has already been read (the message type)\nexport function decodeConnectUsers(\n buffer: BufferReader,\n protocolSubversion: networkedDOMProtocolSubProtocol_v0_2_SubversionNumber,\n): NetworkedDOMV02ConnectUsersMessage {\n const connectionIds: number[] = [];\n const connectionIdsLength = buffer.readUVarint();\n for (let i = 0; i < connectionIdsLength; i++) {\n connectionIds.push(buffer.readUVarint());\n }\n const connectionTokens: Array<string | null> = [];\n if (protocolSubversionHasConnectionTokens(protocolSubversion)) {\n for (let i = 0; i < connectionIdsLength; i++) {\n const token = buffer.readUVarintPrefixedString();\n if (token === \"\") {\n connectionTokens.push(null);\n } else {\n connectionTokens.push(token);\n }\n }\n } else {\n // This client doesn't support connection tokens, so fill with nulls for the server to interpret as \"no token\"\n for (let i = 0; i < connectionIdsLength; i++) {\n connectionTokens.push(null);\n }\n }\n return {\n type: \"connectUsers\",\n connectionIds,\n connectionTokens,\n };\n}\n", "import { BufferReader } from \"../../BufferReader\";\nimport { BufferWriter } from \"../../BufferWriter\";\nimport { DisconnectUsersMessageType } from \"../../messageTypes\";\n\nexport type NetworkedDOMV02DisconnectUsersMessage = {\n type: \"disconnectUsers\";\n connectionIds: Array<number>;\n};\n\nexport function encodeDisconnectUsers(\n disconnectUsersMessage: NetworkedDOMV02DisconnectUsersMessage,\n writer: BufferWriter,\n) {\n const connectionIdsLength = disconnectUsersMessage.connectionIds.length;\n writer.writeUint8(DisconnectUsersMessageType);\n writer.writeUVarint(connectionIdsLength);\n for (let i = 0; i < connectionIdsLength; i++) {\n writer.writeUVarint(disconnectUsersMessage.connectionIds[i]);\n }\n}\n\n// Assumes that the first byte has already been read (the message type)\nexport function decodeDisconnectUsers(buffer: BufferReader): NetworkedDOMV02DisconnectUsersMessage {\n const connectionIds: number[] = [];\n const connectionIdsLength = buffer.readUVarint();\n for (let i = 0; i < connectionIdsLength; i++) {\n connectionIds.push(buffer.readUVarint());\n }\n return {\n type: \"disconnectUsers\",\n connectionIds,\n };\n}\n", "import { BufferReader } from \"../../BufferReader\";\nimport { BufferWriter } from \"../../BufferWriter\";\nimport { EventMessageType } from \"../../messageTypes\";\n\nexport type NetworkedDOMV02RemoteEvent = {\n type: \"event\";\n connectionId: number;\n nodeId: number;\n name: string;\n bubbles: boolean;\n params: any;\n};\n\nexport function encodeEvent(event: NetworkedDOMV02RemoteEvent, writer: BufferWriter) {\n writer.writeUint8(EventMessageType);\n writer.writeUVarint(event.nodeId);\n writer.writeUVarint(event.connectionId);\n writer.writeLengthPrefixedString(event.name);\n writer.writeBoolean(event.bubbles);\n writer.writeLengthPrefixedString(JSON.stringify(event.params));\n}\n\n// Assumes that the first byte has already been read (the message type)\nexport function decodeEvent(buffer: BufferReader): NetworkedDOMV02RemoteEvent {\n const nodeId = buffer.readUVarint();\n const connectionId = buffer.readUVarint();\n const name = buffer.readUVarintPrefixedString();\n const bubbles = buffer.readBoolean();\n const paramsJSONString = buffer.readUVarintPrefixedString();\n const params = JSON.parse(paramsJSONString);\n return {\n type: \"event\",\n nodeId,\n connectionId,\n name,\n bubbles,\n params,\n };\n}\n", "import { BufferReader } from \"../../BufferReader\";\nimport { BufferWriter } from \"../../BufferWriter\";\nimport { PongMessageType } from \"../../messageTypes\";\n\nexport type NetworkedDOMV02PongMessage = {\n type: \"pong\";\n pong: number;\n};\n\nexport function encodePong(pongMessage: NetworkedDOMV02PongMessage, writer: BufferWriter) {\n writer.writeUint8(PongMessageType);\n writer.writeUVarint(pongMessage.pong);\n}\n\n// Assumes that the first byte has already been read (the message type)\nexport function decodePong(buffer: BufferReader): NetworkedDOMV02PongMessage {\n const pong = buffer.readUVarint();\n return {\n type: \"pong\",\n pong,\n };\n}\n", "import { BufferReader } from \"./BufferReader\";\nimport { networkedDOMProtocolSubProtocol_v0_2_SubversionNumber } from \"./constants\";\nimport { NetworkedDOMV02ClientMessage } from \"./messages\";\nimport { decodeConnectUsers } from \"./messages/from-client/connectUsers\";\nimport { decodeDisconnectUsers } from \"./messages/from-client/disconnectUsers\";\nimport { decodeEvent } from \"./messages/from-client/event\";\nimport { decodePong } from \"./messages/from-client/pong\";\nimport {\n ConnectUsersMessageType,\n DisconnectUsersMessageType,\n EventMessageType,\n PongMessageType,\n} from \"./messageTypes\";\n\nexport function decodeClientMessages(\n buffer: BufferReader,\n protocolSubversion: networkedDOMProtocolSubProtocol_v0_2_SubversionNumber,\n): Array<NetworkedDOMV02ClientMessage> {\n const messages: NetworkedDOMV02ClientMessage[] = [];\n while (!buffer.isEnd()) {\n const messageType = buffer.readUInt8();\n switch (messageType) {\n case ConnectUsersMessageType:\n messages.push(decodeConnectUsers(buffer, protocolSubversion));\n break;\n case DisconnectUsersMessageType:\n messages.push(decodeDisconnectUsers(buffer));\n break;\n case EventMessageType:\n messages.push(decodeEvent(buffer));\n break;\n case PongMessageType:\n messages.push(decodePong(buffer));\n break;\n default:\n throw new Error(`Unknown message type: ${messageType}`);\n }\n }\n return messages;\n}\n", "import { BufferReader } from \"../../BufferReader\";\nimport { BufferWriter } from \"../../BufferWriter\";\nimport { decodeAttributes, encodeAttributes } from \"../../common-structs/attributes\";\nimport { AttributesChangedMessageType } from \"../../messageTypes\";\n\nexport type NetworkedDOMV02AttributesChangedDiff = {\n type: \"attributesChanged\";\n nodeId: number;\n attributes: Array<[string, string | null]>;\n documentTime?: number;\n};\n\nexport function encodeAttributesChanged(\n msg: NetworkedDOMV02AttributesChangedDiff,\n writer: BufferWriter = new BufferWriter(64),\n): BufferWriter {\n writer.writeUint8(AttributesChangedMessageType);\n writer.writeUVarint(msg.nodeId);\n encodeAttributes(writer, msg.attributes);\n return writer;\n}\n\n// Assumes that the first byte has already been read (the message type)\nexport function decodeAttributesChanged(\n buffer: BufferReader,\n): NetworkedDOMV02AttributesChangedDiff {\n const nodeId = buffer.readUVarint();\n const attributes = decodeAttributes(buffer);\n return {\n type: \"attributesChanged\",\n nodeId,\n attributes,\n };\n}\n", "import { BufferWriter } from \"../../BufferWriter\";\nimport { BatchEndMessageType } from \"../../messageTypes\";\n\nexport type NetworkedDOMV02BatchEndMessage = {\n type: \"batchEnd\";\n};\n\nexport function encodeBatchEnd(writer: BufferWriter = new BufferWriter(1)): BufferWriter {\n writer.writeUint8(BatchEndMessageType);\n return writer;\n}\n\nexport const batchEndMessage: NetworkedDOMV02BatchEndMessage = {\n type: \"batchEnd\",\n};\n", "import { BufferWriter } from \"../../BufferWriter\";\nimport { BatchStartMessageType } from \"../../messageTypes\";\n\nexport type NetworkedDOMV02BatchStartMessage = {\n type: \"batchStart\";\n};\n\nexport function encodeBatchStart(writer: BufferWriter = new BufferWriter(1)): BufferWriter {\n writer.writeUint8(BatchStartMessageType);\n return writer;\n}\n\nexport const batchStartMessage: NetworkedDOMV02BatchStartMessage = {\n type: \"batchStart\",\n};\n", "import { BufferReader } from \"../../BufferReader\";\nimport { BufferWriter } from \"../../BufferWriter\";\nimport { ChangeHiddenFromMessageType } from \"../../messageTypes\";\n\nexport type NetworkedDOMV02ChangeHiddenFromDiff = {\n type: \"changeHiddenFrom\";\n nodeId: number;\n addHiddenFrom: Array<number>;\n removeHiddenFrom: Array<number>;\n};\n\nexport function encodeChangeHiddenFrom(\n msg: NetworkedDOMV02ChangeHiddenFromDiff,\n writer: BufferWriter = new BufferWriter(64),\n): BufferWriter {\n writer.writeUint8(ChangeHiddenFromMessageType);\n writer.writeUVarint(msg.nodeId);\n\n if (msg.addHiddenFrom) {\n writer.writeUVarint(msg.addHiddenFrom.length);\n\n for (const key of msg.addHiddenFrom) {\n writer.writeUVarint(key);\n }\n } else {\n // If there are no addHiddenFrom, we still need to send a 0 to indicate that there are no entries\n writer.writeUVarint(0);\n }\n if (msg.removeHiddenFrom) {\n writer.writeUVarint(msg.removeHiddenFrom.length);\n\n for (const key of msg.removeHiddenFrom) {\n writer.writeUVarint(key);\n }\n } else {\n // If there are no removeHiddenFrom, we still need to send a 0 to indicate that there are no entries\n writer.writeUVarint(0);\n }\n return writer;\n}\n\n// Assumes that the first byte has already been read (the message type)\nexport function decodeChangeHiddenFrom(buffer: BufferReader): NetworkedDOMV02ChangeHiddenFromDiff {\n const nodeId = buffer.readUVarint();\n const addHiddenFromLength = buffer.readUVarint();\n const addHiddenFrom: number[] = [];\n for (let i = 0; i < addHiddenFromLength; i++) {\n addHiddenFrom.push(buffer.readUVarint());\n }\n\n const removeHiddenFromLength = buffer.readUVarint();\n const removeHiddenFrom: number[] = [];\n for (let i = 0; i < removeHiddenFromLength; i++) {\n removeHiddenFrom.push(buffer.readUVarint());\n }\n\n return {\n type: \"changeHiddenFrom\",\n nodeId,\n addHiddenFrom,\n removeHiddenFrom,\n };\n}\n", "import { BufferReader } from \"../../BufferReader\";\nimport { BufferWriter } from \"../../BufferWriter\";\nimport { ChangeVisibleToMessageType } from \"../../messageTypes\";\n\nexport type NetworkedDOMV02ChangeVisibleToDiff = {\n type: \"changeVisibleTo\";\n nodeId: number;\n /*\n The semantics are that if there are no visibleTo limitations then the node is visible to everyone.\n\n It is advisable to apply the addVisibleTo first before the removeVisibleTo to avoid even a temporary state where a node is visible to everyone between the two operations.\n */\n addVisibleTo: Array<number>;\n removeVisibleTo: Array<number>;\n};\n\nexport function encodeChangeVisibleTo(\n msg: NetworkedDOMV02ChangeVisibleToDiff,\n writer: BufferWriter = new BufferWriter(64),\n): BufferWriter {\n writer.writeUint8(ChangeVisibleToMessageType);\n writer.writeUVarint(msg.nodeId);\n\n if (msg.addVisibleTo) {\n writer.writeUVarint(msg.addVisibleTo.length);\n\n for (const key of msg.addVisibleTo) {\n writer.writeUVarint(key);\n }\n } else {\n // If there are no addVisibleTo, we still need to send a 0 to indicate that there are no entries\n writer.writeUVarint(0);\n }\n if (msg.removeVisibleTo) {\n writer.writeUVarint(msg.removeVisibleTo.length);\n\n for (const key of msg.removeVisibleTo) {\n writer.writeUVarint(key);\n }\n } else {\n // If there are no removeVisibleTo, we still need to send a 0 to indicate that there are no entries\n writer.writeUVarint(0);\n }\n return writer;\n}\n\n// Assumes that the first byte has already been read (the message type)\nexport function decodeChangeVisibleTo(buffer: BufferReader): NetworkedDOMV02ChangeVisibleToDiff {\n const nodeId = buffer.readUVarint();\n const addVisibleToLength = buffer.readUVarint();\n const addVisibleTo: number[] = [];\n for (let i = 0; i < addVisibleToLength; i++) {\n addVisibleTo.push(buffer.readUVarint());\n }\n\n const removeVisibleToLength = buffer.readUVarint();\n const removeVisibleTo: number[] = [];\n for (let i = 0; i < removeVisibleToLength; i++) {\n removeVisibleTo.push(buffer.readUVarint());\n }\n\n return {\n type: \"changeVisibleTo\",\n nodeId,\n addVisibleTo,\n removeVisibleTo,\n };\n}\n", "import { BufferReader } from \"../../BufferReader\";\nimport { BufferWriter } from \"../../BufferWriter\";\nimport {\n decodeNodeDescription,\n encodeNodeDescription,\n NetworkedDOMV02NodeDescription,\n} from \"../../common-structs/nodeDescription\";\nimport { ChildrenAddedMessageType } from \"../../messageTypes\";\n\nexport type NetworkedDOMV02ChildrenAddedDiff = {\n type: \"childrenAdded\";\n nodeId: number;\n previousNodeId: number | null;\n addedNodes: Array<NetworkedDOMV02NodeDescription>;\n};\n\nexport function encodeChildrenAdded(\n msg: NetworkedDOMV02ChildrenAddedDiff,\n writer: BufferWriter = new BufferWriter(64),\n): BufferWriter {\n writer.writeUint8(ChildrenAddedMessageType);\n writer.writeUVarint(msg.nodeId);\n writer.writeUVarint(msg.previousNodeId ?? 0);\n writer.writeUVarint(msg.addedNodes.length);\n for (let i = 0; i < msg.addedNodes.length; i++) {\n encodeNodeDescription(writer, msg.addedNodes[i]);\n }\n return writer;\n}\n\n// Assumes that the first byte has already been read (the message type)\nexport function decodeChildrenAdded(buffer: BufferReader): NetworkedDOMV02ChildrenAddedDiff {\n const nodeId = buffer.readUVarint();\n const previousNodeId = buffer.readUVarint();\n const childrenLength = buffer.readUVarint();\n const children: NetworkedDOMV02NodeDescription[] = [];\n for (let i = 0; i < childrenLength; i++) {\n children.push(decodeNodeDescription(buffer));\n }\n return {\n type: \"childrenAdded\",\n nodeId,\n previousNodeId: previousNodeId === 0 ? null : previousNodeId,\n addedNodes: children,\n };\n}\n", "import { BufferReader } from \"../../BufferReader\";\nimport { BufferWriter } from \"../../BufferWriter\";\nimport { ChildrenRemovedMessageType } from \"../../messageTypes\";\n\nexport type NetworkedDOMV02ChildrenRemovedDiff = {\n type: \"childrenRemoved\";\n nodeId: number;\n removedNodes: Array<number>;\n documentTime?: number;\n};\n\nexport function encodeChildrenRemoved(\n msg: NetworkedDOMV02ChildrenRemovedDiff,\n writer: BufferWriter = new BufferWriter(64),\n): BufferWriter {\n writer.writeUint8(ChildrenRemovedMessageType);\n writer.writeUVarint(msg.nodeId);\n writer.writeUVarint(msg.removedNodes.length);\n for (const nodeId of msg.removedNodes) {\n writer.writeUVarint(nodeId);\n }\n return writer;\n}\n\n// Assumes that the first byte has already been read (the message type)\nexport function decodeChildrenRemoved(buffer: BufferReader): NetworkedDOMV02ChildrenRemovedDiff {\n const nodeId = buffer.readUVarint();\n const removedNodesLength = buffer.readUVarint();\n const removedNodes: number[] = [];\n for (let i = 0; i < removedNodesLength; i++) {\n removedNodes.push(buffer.readUVarint());\n }\n return {\n type: \"childrenRemoved\",\n nodeId,\n removedNodes,\n };\n}\n", "import { BufferReader } from \"../../BufferReader\";\nimport { BufferWriter } from \"../../BufferWriter\";\nimport { DocumentTimeMessageType } from \"../../messageTypes\";\n\nexport type NetworkedDOMV02DocumentTimeMessage = {\n type: \"documentTime\";\n documentTime: number;\n};\n\nexport function encodeDocumentTime(\n msg: NetworkedDOMV02DocumentTimeMessage,\n writer: BufferWriter = new BufferWriter(8),\n): BufferWriter {\n writer.writeUint8(DocumentTimeMessageType);\n writer.writeUVarint(msg.documentTime);\n return writer;\n}\n\n// Assumes that the first byte has already been read (the message type)\nexport function decodeDocumentTime(buffer: BufferReader): NetworkedDOMV02DocumentTimeMessage {\n return {\n type: \"documentTime\",\n documentTime: buffer.readUVarint(),\n };\n}\n", "import { BufferReader } from \"../../BufferReader\";\nimport { BufferWriter } from \"../../BufferWriter\";\nimport { ErrorMessageType } from \"../../messageTypes\";\n\nexport type NetworkedDOMV02ErrorMessage = {\n type: \"error\";\n message: string;\n};\n\nexport function encodeError(\n msg: NetworkedDOMV02ErrorMessage,\n writer: BufferWriter = new BufferWriter(64),\n): BufferWriter {\n writer.writeUint8(ErrorMessageType);\n writer.writeLengthPrefixedString(msg.message);\n return writer;\n}\n\n// Assumes that the first byte has already been read (the message type)\nexport function decodeError(buffer: BufferReader): NetworkedDOMV02ErrorMessage {\n const message = buffer.readUVarintPrefixedString();\n return {\n type: \"error\",\n message,\n };\n}\n", "import { BufferReader } from \"../../BufferReader\";\nimport { BufferWriter } from \"../../BufferWriter\";\nimport { PingMessageType } from \"../../messageTypes\";\n\nexport type NetworkedDOMV02PingMessage = {\n type: \"ping\";\n ping: number;\n documentTime: number;\n};\n\nexport function encodePing(\n pingMessage: NetworkedDOMV02PingMessage,\n writer: BufferWriter = new BufferWriter(8),\n): BufferWriter {\n writer.writeUint8(PingMessageType);\n writer.writeUVarint(pingMessage.ping);\n writer.writeUVarint(pingMessage.documentTime);\n return writer;\n}\n\n// Assumes that the first byte has already been read (the message type)\nexport function decodePing(buffer: BufferReader): NetworkedDOMV02PingMessage {\n const ping = buffer.readUVarint();\n const documentTime = buffer.readUVarint();\n return {\n type: \"ping\",\n ping,\n documentTime,\n };\n}\n", "import { BufferReader } from \"../../BufferReader\";\nimport { BufferWriter } from \"../../BufferWriter\";\nimport {\n decodeNodeDescription,\n encodeNodeDescription,\n NetworkedDOMV02ElementNodeDescription,\n NetworkedDOMV02NodeDescription,\n} from \"../../common-structs/nodeDescription\";\nimport { SnapshotMessageType } from \"../../messageTypes\";\n\nexport type NetworkedDOMV02SnapshotMessage = {\n type: \"snapshot\";\n snapshot: NetworkedDOMV02NodeDescription;\n documentTime: number;\n};\n\nexport function encodeSnapshot(\n msg: NetworkedDOMV02SnapshotMessage,\n writer: BufferWriter = new BufferWriter(64),\n): BufferWriter {\n writer.writeUint8(SnapshotMessageType);\n encodeNodeDescription(writer, msg.snapshot as NetworkedDOMV02ElementNodeDescription);\n writer.writeUVarint(msg.documentTime);\n return writer;\n}\n\n// Assumes that the first byte has already been read (the message type)\nexport function decodeSnapshot(buffer: BufferReader): NetworkedDOMV02SnapshotMessage {\n return {\n type: \"snapshot\",\n snapshot: decodeNodeDescription(buffer),\n documentTime: buffer.readUVarint(),\n };\n}\n", "import { BufferReader } from \"../../BufferReader\";\nimport { BufferWriter } from \"../../BufferWriter\";\nimport { TextChangedMessageType } from \"../../messageTypes\";\n\nexport type NetworkedDOMV02TextChangedDiff = {\n type: \"textChanged\";\n nodeId: number;\n text: string;\n};\n\nexport function encodeTextChanged(\n msg: NetworkedDOMV02TextChangedDiff,\n writer: BufferWriter = new BufferWriter(64),\n): BufferWriter {\n writer.writeUint8(TextChangedMessageType);\n writer.writeUVarint(msg.nodeId);\n writer.writeLengthPrefixedString(msg.text);\n return writer;\n}\n\n// Assumes that the first byte has already been read (the message type)\nexport function decodeTextChanged(buffer: BufferReader): NetworkedDOMV02TextChangedDiff {\n const nodeId = buffer.readUVarint();\n const text = buffer.readUVarintPrefixedString();\n return {\n type: \"textChanged\",\n nodeId,\n text,\n };\n}\n", "import { BufferReader } from \"../../BufferReader\";\nimport { BufferWriter } from \"../../BufferWriter\";\nimport { WarningMessageType } from \"../../messageTypes\";\n\nexport type NetworkedDOMV02WarningMessage = {\n type: \"warning\";\n message: string;\n};\n\nexport function encodeWarning(\n msg: NetworkedDOMV02WarningMessage,\n writer: BufferWriter = new BufferWriter(64),\n): BufferWriter {\n writer.writeUint8(WarningMessageType);\n writer.writeLengthPrefixedString(msg.message);\n return writer;\n}\n\n// Assumes that the first byte has already been read (the message type)\nexport function decodeWarning(buffer: BufferReader): NetworkedDOMV02WarningMessage {\n const message = buffer.readUVarintPrefixedString();\n return {\n type: \"warning\",\n message,\n };\n}\n", "import { BufferReader } from \"./BufferReader\";\nimport {\n batchEndMessage,\n batchStartMessage,\n decodeAttributesChanged,\n decodeChangeHiddenFrom,\n decodeChangeVisibleTo,\n decodeChildrenAdded,\n decodeChildrenRemoved,\n decodeError,\n decodePing,\n decodeSnapshot,\n decodeTextChanged,\n decodeWarning,\n NetworkedDOMV02ServerMessage,\n} from \"./messages\";\nimport { decodeDocumentTime } from \"./messages/from-server/documentTime\";\nimport {\n AttributesChangedMessageType,\n BatchEndMessageType,\n BatchStartMessageType,\n ChangeHiddenFromMessageType,\n ChangeVisibleToMessageType,\n ChildrenAddedMessageType,\n ChildrenRemovedMessageType,\n DocumentTimeMessageType,\n ErrorMessageType,\n PingMessageType,\n SnapshotMessageType,\n TextChangedMessageType,\n WarningMessageType,\n} from \"./messageTypes\";\n\nexport function decodeServerMessages(buffer: BufferReader): Array<NetworkedDOMV02ServerMessage> {\n const messages: NetworkedDOMV02ServerMessage[] = [];\n while (!buffer.isEnd()) {\n const messageType = buffer.readUInt8();\n switch (messageType) {\n case SnapshotMessageType:\n messages.push(decodeSnapshot(buffer));\n break;\n case DocumentTimeMessageType:\n messages.push(decodeDocumentTime(buffer));\n break;\n case ChildrenAddedMessageType:\n messages.push(decodeChildrenAdded(buffer));\n break;\n case ChildrenRemovedMessageType:\n messages.push(decodeChildrenRemoved(buffer));\n break;\n case AttributesChangedMessageType:\n messages.push(decodeAttributesChanged(buffer));\n break;\n case TextChangedMessageType:\n messages.push(decodeTextChanged(buffer));\n break;\n case ChangeVisibleToMessageType:\n messages.push(decodeChangeVisibleTo(buffer));\n break;\n case ChangeHiddenFromMessageType:\n messages.push(decodeChangeHiddenFrom(buffer));\n break;\n case BatchStartMessageType:\n messages.push(batchStartMessage);\n break;\n case BatchEndMessageType:\n messages.push(batchEndMessage);\n break;\n case PingMessageType:\n messages.push(decodePing(buffer));\n break;\n case WarningMessageType:\n messages.push(decodeWarning(buffer));\n break;\n case ErrorMessageType:\n messages.push(decodeError(buffer));\n break;\n default:\n throw new Error(`Unknown message type: ${messageType}`);\n }\n }\n return messages;\n}\n", "import { BufferWriter } from \"./BufferWriter\";\nimport { networkedDOMProtocolSubProtocol_v0_2_SubversionNumber } from \"./constants\";\nimport {\n encodeConnectUsers,\n encodeDisconnectUsers,\n encodeEvent,\n encodePong,\n NetworkedDOMV02ClientMessage,\n} from \"./messages\";\n\nexport function encodeClientMessage(\n message: NetworkedDOMV02ClientMessage,\n writer: BufferWriter,\n protocolSubversion: networkedDOMProtocolSubProtocol_v0_2_SubversionNumber,\n) {\n const type = message.type;\n switch (type) {\n case \"connectUsers\":\n return encodeConnectUsers(message, writer, protocolSubversion);\n case \"disconnectUsers\":\n return encodeDisconnectUsers(message, writer);\n case \"event\":\n return encodeEvent(message, writer);\n case \"pong\":\n return encodePong(message, writer);\n default:\n throw new Error(`Unknown message type: ${type}`);\n }\n}\n", "import { BufferWriter } from \"./BufferWriter\";\nimport {\n encodeBatchEnd,\n encodeBatchStart,\n encodeTextChanged,\n NetworkedDOMV02ServerMessage,\n} from \"./messages\";\nimport { encodeAttributesChanged } from \"./messages/from-server/attributesChanged\";\nimport { encodeChangeHiddenFrom } from \"./messages/from-server/changeHiddenFrom\";\nimport { encodeChangeVisibleTo } from \"./messages/from-server/changeVisibleTo\";\nimport { encodeChildrenAdded } from \"./messages/from-server/childrenAdded\";\nimport { encodeChildrenRemoved } from \"./messages/from-server/childrenRemoved\";\nimport { encodeDocumentTime } from \"./messages/from-server/documentTime\";\nimport { encodeError } from \"./messages/from-server/error\";\nimport { encodePing } from \"./messages/from-server/ping\";\nimport { encodeSnapshot } from \"./messages/from-server/snapshot\";\nimport { encodeWarning } from \"./messages/from-server/warning\";\n\nexport function encodeServerMessage(\n message: NetworkedDOMV02ServerMessage,\n writer?: BufferWriter,\n): BufferWriter {\n switch (message.type) {\n case \"snapshot\":\n return encodeSnapshot(message, writer);\n case \"documentTime\":\n return encodeDocumentTime(message, writer);\n case \"childrenAdded\":\n return encodeChildrenAdded(message, writer);\n case \"childrenRemoved\":\n return encodeChildrenRemoved(message, writer);\n case \"attributesChanged\":\n return encodeAttributesChanged(message, writer);\n case \"textChanged\":\n return encodeTextChanged(message, writer);\n case \"changeVisibleTo\":\n return encodeChangeVisibleTo(message, writer);\n case \"changeHiddenFrom\":\n return encodeChangeHiddenFrom(message, writer);\n case \"batchStart\":\n return encodeBatchStart(writer);\n case \"batchEnd\":\n return encodeBatchEnd(writer);\n case \"ping\":\n return encodePing(message, writer);\n case \"warning\":\n return encodeWarning(message, writer);\n case \"error\":\n return encodeError(message, writer);\n default:\n throw new Error(`Unknown message type: ${(message as any).type}`);\n }\n}\n", "export type DOMSanitizerOptions = {\n tagPrefix?: string; // e.g. \"m-\" to restrict to only custom elements with a tag name starting with \"m-\"\n replacementTagPrefix?: string; // e.g. \"x-\" to replace non-prefixed tags with a new prefix (e.g. \"div\" -> \"x-div\")\n};\n\nexport class DOMSanitizer {\n static sanitise(node: HTMLElement, options: DOMSanitizerOptions = {}) {\n if (node.getAttributeNames) {\n for (const attr of node.getAttributeNames()) {\n if (!DOMSanitizer.IsValidAttributeName(attr)) {\n node.removeAttribute(attr);\n }\n }\n }\n\n if (node instanceof HTMLElement) {\n if (options.tagPrefix) {\n const tag = node.nodeName.toLowerCase();\n if (!tag.startsWith(options.tagPrefix.toLowerCase())) {\n node = DOMSanitizer.replaceNodeTagName(\n node,\n options.replacementTagPrefix ? options.replacementTagPrefix + tag : `x-${tag}`,\n );\n }\n }\n }\n\n if (node.nodeName === \"SCRIPT\" || node.nodeName === \"OBJECT\" || node.nodeName === \"IFRAME\") {\n // set contents to empty string\n node.innerHTML = \"\";\n DOMSanitizer.stripAllAttributes(node);\n } else {\n if (node.getAttributeNames) {\n for (const attr of node.getAttributeNames()) {\n if (!DOMSanitizer.shouldAcceptAttribute(attr)) {\n node.removeAttribute(attr);\n }\n }\n }\n for (let i = 0; i < node.childNodes.length; i++) {\n DOMSanitizer.sanitise(node.childNodes[i] as HTMLElement, options);\n }\n }\n return node;\n }\n\n static replaceNodeTagName(node: HTMLElement, newTagName: string) {\n const replacementNode = document.createElement(newTagName);\n let index;\n while (node.firstChild) {\n replacementNode.appendChild(node.firstChild);\n }\n for (index = node.attributes.length - 1; index >= 0; --index) {\n replacementNode.setAttribute(node.attributes[index].name, node.attributes[index].value);\n }\n node.parentNode?.replaceChild(replacementNode, node);\n return replacementNode;\n }\n\n static stripAllAttributes(node: HTMLElement) {\n if (node.getAttributeNames) {\n for (const attr of node.getAttributeNames()) {\n node.removeAttribute(attr);\n }\n }\n }\n\n static IsASCIIDigit(c: string): boolean {\n return c >= \"0\" && c <= \"9\";\n }\n\n static IsASCIIAlpha(c: string) {\n return (c >= \"a\" && c <= \"z\") || (c >= \"A\" && c <= \"Z\");\n }\n\n static IsValidAttributeName(characters: string): boolean {\n const c = characters[0];\n if (!(DOMSanitizer.IsASCIIAlpha(c) || c === \":\" || c === \"_\")) {\n return false;\n }\n\n for (let i = 1; i < characters.length; i++) {\n const c = characters[i];\n if (\n !(\n DOMSanitizer.IsASCIIDigit(c) ||\n DOMSanitizer.IsASCIIAlpha(c) ||\n c === \":\" ||\n c === \"_\" ||\n c === \"-\" ||\n c === \".\"\n )\n ) {\n return false;\n }\n }\n\n return true;\n }\n\n static shouldAcceptAttribute(attribute: string) {\n if (!DOMSanitizer.IsValidAttributeName(attribute)) {\n console.warn(\"Invalid attribute name\", attribute);\n return false;\n }\n\n // TODO - this might be overly restrictive - apologies to someone that finds this because you have a non-event attribute filtered by this\n return !attribute.startsWith(\"on\");\n }\n}\n", "import {\n isNetworkedDOMProtocolSubProtocol_v0_2,\n networkedDOMProtocolSubProtocol_v0_1,\n networkedDOMProtocolSubProtocol_v0_2_SubVersionsList,\n} from \"@mml-io/networked-dom-protocol\";\n\nimport { NetworkedDOMWebsocketV01Adapter } from \"./NetworkedDOMWebsocketV01Adapter\";\nimport { NetworkedDOMWebsocketV02Adapter } from \"./NetworkedDOMWebsocketV02Adapter\";\n\nconst startingBackoffTimeMilliseconds = 100;\nconst maximumBackoffTimeMilliseconds = 10000;\nconst maximumWebsocketConnectionTimeout = 5000;\n\nexport type NetworkedDOMWebsocketFactory = (url: string) => WebSocket;\n\nexport enum NetworkedDOMWebsocketStatus {\n Connecting,\n ConnectionOpen, // The websocket is open and connected, but no messages have been received yet\n Connected, // The websocket is open and connected, and messages are being received\n Reconnecting,\n Disconnected,\n}\n\nexport function NetworkedDOMWebsocketStatusToString(status: NetworkedDOMWebsocketStatus): string {\n switch (status) {\n case NetworkedDOMWebsocketStatus.Connecting:\n return \"Connecting...\";\n case NetworkedDOMWebsocketStatus.ConnectionOpen:\n return \"Connection Open\";\n case NetworkedDOMWebsocketStatus.Connected:\n return \"Connected\";\n case NetworkedDOMWebsocketStatus.Reconnecting:\n return \"Reconnecting...\";\n case NetworkedDOMWebsocketStatus.Disconnected:\n return \"Disconnected\";\n default:\n return \"Unknown\";\n }\n}\n\nexport type NetworkedDOMWebsocketOptions = {\n tagPrefix?: string; // e.g. \"m-\" to restrict to only custom elements with a tag name starting with \"m-\"\n replacementTagPrefix?: string; // e.g. \"x-\" to replace non-prefixed tags with a new prefix (e.g. \"div\" -> \"x-div\")\n allowSVGElements?: boolean; // Whether to allow SVG namespace elements to be created. Default is false.\n connectionToken?: string | null; // Optional token to send to the server for authentication/authorization\n};\n\nexport type NetworkedDOMWebsocketAdapter = {\n receiveMessage: (message: MessageEvent) => void;\n handleEvent: (element: HTMLElement, event: CustomEvent<{ element: HTMLElement }>) => void;\n clearContents: () => boolean;\n};\n\n/**\n * NetworkedDOMWebsocket is a client for a NetworkedDOMServer. It connects to a server on the provided url and receives\n * updates to the DOM. It also sends events to the server for interactions with the DOM.\n *\n * The NetworkedDOMWebsocket is attached to a parentElement and synchronizes the received DOM under that element.\n */\nexport class NetworkedDOMWebsocket {\n private websocket: WebSocket | null = null;\n private websocketAdapter: NetworkedDOMWebsocketAdapter | null = null;\n\n private stopped = false;\n private backoffTime = startingBackoffTimeMilliseconds;\n private status: NetworkedDOMWebsocketStatus | null = null;\n\n public static createWebSocket(url: string): WebSocket {\n return new WebSocket(url, [\n ...networkedDOMProtocolSubProtocol_v0_2_SubVersionsList,\n networkedDOMProtocolSubProtocol_v0_1,\n ]);\n }\n\n constructor(\n private url: string,\n private websocketFactory: NetworkedDOMWebsocketFactory,\n private parentElement: HTMLElement,\n private timeCallback?: (time: number) => void,\n private statusUpdateCallback?: (status: NetworkedDOMWebsocketStatus) => void,\n private options: NetworkedDOMWebsocketOptions = {},\n ) {\n this.setStatus(NetworkedDOMWebsocketStatus.Connecting);\n this.startWebSocketConnectionAttempt();\n }\n\n private setStatus(status: NetworkedDOMWebsocketStatus) {\n if (this.status !== status) {\n this.status = status;\n if (this.statusUpdateCallback) {\n this.statusUpdateCallback(status);\n }\n }\n }\n\n private createWebsocketWithTimeout(timeout: number): Promise<WebSocket> {\n return new Promise((resolve, reject) => {\n const websocket = this.websocketFactory(this.url);\n const timeoutId = setTimeout(() => {\n reject(new Error(\"websocket connection timed out\"));\n websocket.close();\n }, timeout);\n websocket.binaryType = \"arraybuffer\";\n websocket.addEventListener(\"open\", () => {\n clearTimeout(timeoutId);\n\n this.websocket = websocket;\n const isV02 = isNetworkedDOMProtocolSubProtocol_v0_2(websocket.protocol);\n let websocketAdapter: NetworkedDOMWebsocketAdapter;\n if (isV02) {\n websocketAdapter = new NetworkedDOMWebsocketV02Adapter(\n websocket,\n this.parentElement,\n () => {\n this.backoffTime = startingBackoffTimeMilliseconds;\n this.setStatus(NetworkedDOMWebsocketStatus.Connected);\n },\n this.timeCallback,\n this.options,\n );\n } else {\n websocketAdapter = new NetworkedDOMWebsocketV01Adapter(\n websocket,\n this.parentElement,\n () => {\n this.backoffTime = startingBackoffTimeMilliseconds;\n this.setStatus(NetworkedDOMWebsocketStatus.Connected);\n },\n this.timeCallback,\n this.options,\n );\n }\n this.websocketAdapter = websocketAdapter;\n\n websocket.addEventListener(\"message\", (event) => {\n if (websocket !== this.websocket) {\n console.log(\"Ignoring websocket message event because it is no longer current\");\n websocket.close();\n return;\n }\n websocketAdapter.receiveMessage(event);\n });\n\n const onWebsocketClose = async () => {\n let hadContents = false;\n if (this.websocketAdapter) {\n hadContents = this.websocketAdapter.clearContents();\n }\n if (this.stopped) {\n // This closing is expected. The client closed the websocket.\n this.setStatus(NetworkedDOMWebsocketStatus.Disconnected);\n return;\n }\n if (!hadContents) {\n // The websocket did not deliver any contents. It may have been successfully opened, but immediately closed. This client should back off to prevent this happening in a rapid loop.\n await this.waitBackoffTime();\n }\n // The websocket closed unexpectedly. Try to reconnect.\n this.setStatus(NetworkedDOMWebsocketStatus.Reconnecting);\n this.startWebSocketConnectionAttempt();\n };\n\n websocket.addEventListener(\"close\", () => {\n if (websocket !== this.websocket) {\n console.warn(\"Ignoring websocket close event because it is no longer current\");\n return;\n }\n onWebsocketClose();\n });\n websocket.addEventListener(\"error\", (e) => {\n if (websocket !== this.websocket) {\n console.log(\"Ignoring websocket error event because it is no longer current\");\n return;\n }\n console.error(\"NetworkedDOMWebsocket error\", e);\n onWebsocketClose();\n });\n\n this.setStatus(NetworkedDOMWebsocketStatus.ConnectionOpen);\n resolve(websocket);\n });\n websocket.addEventListener(\"error\", (e) => {\n clearTimeout(timeoutId);\n reject(e);\n });\n });\n }\n\n private async waitBackoffTime(): Promise<void> {\n console.warn(`Websocket connection to '${this.url}' failed: retrying in ${this.backoffTime}ms`);\n await new Promise((resolve) => setTimeout(resolve, this.backoffTime));\n this.backoffTime = Math.min(\n // Introduce a small amount of randomness to prevent clients from retrying in lockstep\n this.backoffTime * (1.5 + Math.random() * 0.5),\n maximumBackoffTimeMilliseconds,\n );\n }\n\n private async startWebSocketConnectionAttempt() {\n if (this.stopped) {\n return;\n }\n while (true) {\n if (this.stopped) {\n return;\n }\n try {\n await this.createWebsocketWithTimeout(maximumWebsocketConnectionTimeout);\n break;\n } catch (e) {\n console.error(\"Websocket connection failed\", e);\n // Connection failed, retry with backoff\n this.setStatus(NetworkedDOMWebsocketStatus.Reconnecting);\n await this.waitBackoffTime();\n }\n }\n }\n\n public stop() {\n this.stopped = true;\n if (this.websocket !== null) {\n this.websocket.close();\n this.websocket = null;\n }\n }\n\n public handleEvent(element: HTMLElement, event: CustomEvent<{ element: HTMLElement }>) {\n if (this.websocketAdapter) {\n this.websocketAdapter.handleEvent(element, event);\n }\n }\n}\n\nexport function isHTMLElement(node: unknown, rootNode: HTMLElement): node is HTMLElement {\n if (node instanceof HTMLElement || node instanceof Element) {\n return true;\n }\n if (!rootNode.ownerDocument.defaultView) {\n return false;\n }\n return node instanceof rootNode.ownerDocument.defaultView.HTMLElement;\n}\n\nexport function isText(node: unknown, rootNode: HTMLElement): node is Text {\n if (node instanceof Text) {\n return true;\n }\n if (!rootNode.ownerDocument.defaultView) {\n return false;\n }\n return node instanceof rootNode.ownerDocument.defaultView.Text;\n}\n", "import { DOMSanitizer } from \"./DOMSanitizer\";\nimport { NetworkedDOMWebsocketOptions } from \"./NetworkedDOMWebsocket\";\n\n// These tags are always disallowed because they allow arbitrary HTML to be injected\nconst ALWAYS_DISALLOWED_TAGS = new Set([\"foreignobject\", \"iframe\", \"script\"]);\n\nconst SVG_TAG_NAMES_ADJUSTMENT_MAP = new Map(\n [\n \"svg\",\n \"defs\",\n \"g\",\n \"text\",\n \"filter\",\n \"stop\",\n \"path\",\n \"rect\",\n \"line\",\n \"circle\",\n \"animate\",\n \"altGlyph\",\n \"altGlyphDef\",\n \"altGlyphItem\",\n \"animateColor\",\n \"animateMotion\",\n \"animateTransform\",\n \"clipPath\",\n \"feBlend\",\n \"feDropShadow\",\n \"feColorMatrix\",\n \"feComponentTransfer\",\n \"feComposite\",\n \"feConvolveMatrix\",\n \"feDiffuseLighting\",\n \"feDisplacementMap\",\n \"feDistantLight\",\n \"feFlood\",\n \"feFuncA\",\n \"feFuncB\",\n \"feFuncG\",\n \"feFuncR\",\n \"feGaussianBlur\",\n \"feImage\",\n \"feMerge\",\n \"feMergeNode\",\n \"feMorphology\",\n \"feOffset\",\n \"fePointLight\",\n \"feSpecularLighting\",\n \"feSpotLight\",\n \"feTile\",\n \"feTurbulence\",\n \"glyphRef\",\n \"linearGradient\",\n \"radialGradient\",\n \"textPath\",\n // `foreignObject` is explicitly disallowed because it allows injecting arbitrary HTML\n // \"foreignObject\",\n ].map((tn) => [tn.toLowerCase(), tn]),\n);\n\nconst SVG_ATTRS_ADJUSTMENT_MAP = new Map(\n [\n \"attributeName\",\n \"attributeType\",\n \"baseFrequency\",\n \"baseProfile\",\n \"calcMode\",\n \"clipPathUnits\",\n \"diffuseConstant\",\n \"edgeMode\",\n \"filterUnits\",\n \"glyphRef\",\n \"gradientTransform\",\n \"gradientUnits\",\n \"kernelMatrix\",\n \"kernelUnitLength\",\n \"keyPoints\",\n \"keySplines\",\n \"keyTimes\",\n \"lengthAdjust\",\n \"limitingConeAngle\",\n \"markerHeight\",\n \"markerUnits\",\n \"markerWidth\",\n \"maskContentUnits\",\n \"maskUnits\",\n \"numOctaves\",\n \"pathLength\",\n \"patternContentUnits\",\n \"patternTransform\",\n \"patternUnits\",\n \"pointsAtX\",\n \"pointsAtY\",\n \"pointsAtZ\",\n \"preserveAlpha\",\n \"preserveAspectRatio\",\n \"primitiveUnits\",\n \"refX\",\n \"refY\",\n \"repeatCount\",\n \"repeatDur\",\n \"requiredExtensions\",\n \"requiredFeatures\",\n \"specularConstant\",\n \"specularExponent\",\n \"spreadMethod\",\n \"startOffset\",\n \"stdDeviation\",\n \"stitchTiles\",\n \"surfaceScale\",\n \"systemLanguage\",\n \"tableValues\",\n \"targetX\",\n \"targetY\",\n \"textLength\",\n \"viewBox\",\n \"viewTarget\",\n \"xChannelSelector\",\n \"yChannelSelector\",\n \"zoomAndPan\",\n ].map((attr) => [attr.toLowerCase(), attr]),\n);\n\n/**\n * Remaps attribute names to their proper case for SVG elements\n */\nexport function remapAttributeName(attrName: string): string {\n const remapped = SVG_ATTRS_ADJUSTMENT_MAP.get(attrName.toLowerCase());\n if (remapped) {\n return remapped;\n }\n return attrName;\n}\n\n/**\n * Creates an HTML Element (and optionally SVG Elements) with proper namespace handling\n */\nexport function createElementWithSVGSupport(\n tag: string,\n options: NetworkedDOMWebsocketOptions = {},\n): Element {\n let filteredTag = tag.toLowerCase();\n\n if (ALWAYS_DISALLOWED_TAGS.has(filteredTag.toLowerCase())) {\n console.error(\"Disallowing tag\", filteredTag);\n filteredTag = options.replacementTagPrefix ? options.replacementTagPrefix + tag : `x-${tag}`;\n }\n\n let svgTagMapping;\n if (options.allowSVGElements) {\n svgTagMapping = SVG_TAG_NAMES_ADJUSTMENT_MAP.get(filteredTag);\n }\n\n if (svgTagMapping) {\n filteredTag = svgTagMapping;\n const xmlns = \"http://www.w3.org/2000/svg\";\n return document.createElementNS(xmlns, filteredTag);\n } else {\n if (options.tagPrefix) {\n if (!tag.toLowerCase().startsWith(options.tagPrefix.toLowerCase())) {\n filteredTag = options.replacementTagPrefix\n ? options.replacementTagPrefix + tag\n : `x-${tag}`;\n }\n }\n return document.createElement(filteredTag);\n }\n}\n\n/**\n * Sets attributes on an element with proper SVG attribute name mapping\n */\nexport function setElementAttribute(element: Element, key: string, value: string): void {\n if (DOMSanitizer.shouldAcceptAttribute(key)) {\n const remappedKey = remapAttributeName(key);\n element.setAttribute(remappedKey, value);\n }\n}\n\n/**\n * Gets the target element for children operations, handling portal elements\n */\nexport function getChildrenTarget(parent: Element): Element {\n let targetForChildren = parent;\n if ((parent as any).getPortalElement) {\n targetForChildren = (parent as any).getPortalElement();\n }\n return targetForChildren;\n}\n\n/**\n * Gets the target element for removal operations, handling portal elements\n */\nexport function getRemovalTarget(parent: Element): Element {\n let targetForRemoval = parent;\n if ((parent as any).getPortalElement) {\n targetForRemoval = (parent as any).getPortalElement();\n }\n return targetForRemoval;\n}\n", "import {\n NetworkedDOMV01AttributeChangedDiff,\n NetworkedDOMV01ChildrenChangedDiff,\n NetworkedDOMV01ClientMessage,\n NetworkedDOMV01NodeDescription,\n NetworkedDOMV01RemoteEvent,\n NetworkedDOMV01ServerMessage,\n NetworkedDOMV01SnapshotMessage,\n NetworkedDOMV01TextChangedDiff,\n} from \"@mml-io/networked-dom-protocol\";\n\nimport {\n createElementWithSVGSupport,\n getChildrenTarget,\n getRemovalTarget,\n setElementAttribute,\n} from \"./ElementUtils\";\nimport {\n isHTMLElement,\n isText,\n NetworkedDOMWebsocketAdapter,\n NetworkedDOMWebsocketOptions,\n} from \"./NetworkedDOMWebsocket\";\n\nexport class NetworkedDOMWebsocketV01Adapter implements NetworkedDOMWebsocketAdapter {\n private idToElement = new Map<number, Node>();\n private elementToId = new Map<Node, number>();\n private currentRoot: HTMLElement | null = null;\n\n constructor(\n private websocket: WebSocket,\n private parentElement: HTMLElement,\n private connectedCallback: () => void,\n private timeCallback?: (time: number) => void,\n private options: NetworkedDOMWebsocketOptions = {},\n ) {\n this.websocket.binaryType = \"arraybuffer\";\n }\n\n public handleEvent(element: HTMLElement, event: CustomEvent<{ element: HTMLElement }>) {\n const nodeId = this.elementToId.get(element);\n if (nodeId === undefined || nodeId === null) {\n throw new Error(\"Element not found\");\n }\n\n const detailWithoutElement: Partial<typeof event.detail> = {\n ...event.detail,\n };\n delete detailWithoutElement.element;\n\n const remoteEvent: NetworkedDOMV01RemoteEvent = {\n type: \"event\",\n nodeId,\n name: event.type,\n bubbles: event.bubbles,\n params: detailWithoutElement,\n };\n\n this.send(remoteEvent);\n }\n\n private send(fromClientMessage: NetworkedDOMV01ClientMessage) {\n this.websocket.send(JSON.stringify(fromClientMessage));\n }\n\n public clearContents(): boolean {\n this.idToElement.clear();\n this.elementToId.clear();\n if (this.currentRoot) {\n this.currentRoot.remove();\n this.currentRoot = null;\n return true;\n }\n return false;\n }\n\n receiveMessage(event: MessageEvent) {\n const messages = JSON.parse(event.data) as Array<NetworkedDOMV01ServerMessage>;\n for (const message of messages) {\n switch (message.type) {\n case \"error\":\n console.error(\"Error from server\", message);\n break;\n case \"warning\":\n console.warn(\"Warning from server\", message);\n break;\n default: {\n if (message.documentTime) {\n if (this.timeCallback) {\n this.timeCallback(message.documentTime);\n }\n }\n switch (message.type) {\n case \"snapshot\":\n this.handleSnapshot(message);\n this.connectedCallback();\n break;\n case \"attributeChange\":\n this.handleAttributeChange(message);\n break;\n case \"childrenChanged\":\n this.handleChildrenChanged(message);\n break;\n case \"textChanged\":\n this.handleTextChanged(message);\n break;\n case \"ping\":\n this.send({\n type: \"pong\",\n pong: message.ping,\n });\n break;\n default:\n console.warn(\"unknown message type\", message);\n break;\n }\n }\n }\n }\n }\n\n private handleTextChanged(message: NetworkedDOMV01TextChangedDiff) {\n const { nodeId, text } = message;\n\n if (nodeId === undefined || nodeId === null) {\n console.warn(\"No nodeId in textChanged message\");\n return;\n }\n const node = this.idToElement.get(nodeId);\n if (!node) {\n throw new Error(\"No node found for textChanged message\");\n }\n if (!isText(node, this.parentElement)) {\n throw new Error(\"Node for textChanged message is not a Text node\");\n }\n node.textContent = text;\n }\n\n private handleChildrenChanged(message: NetworkedDOMV01ChildrenChangedDiff) {\n const { nodeId, addedNodes, removedNodes, previousNodeId } = message;\n if (nodeId === undefined || nodeId === null) {\n console.warn(\"No nodeId in childrenChanged message\");\n return;\n }\n const parent = this.idToElement.get(nodeId);\n if (!parent) {\n throw new Error(\"No parent found for childrenChanged message\");\n }\n if (!parent.isConnected) {\n console.error(\"Parent is not connected\", parent);\n }\n if (!isHTMLElement(parent, this.parentElement)) {\n throw new Error(\"Parent is not an HTMLElement (that supports children)\");\n }\n\n const targetForChildren = getChildrenTarget(parent);\n\n let nextElement = null;\n let previousElement = null;\n if (previousNodeId) {\n previousElement = this.idToElement.get(previousNodeId);\n if (!previousElement) {\n throw new Error(\"No previous element found for childrenChanged message\");\n }\n nextElement = previousElement.nextSibling;\n }\n\n const elementsToAdd = [];\n for (const addedNode of addedNodes) {\n const childElement = this.handleNewElement(addedNode);\n if (childElement) {\n elementsToAdd.push(childElement);\n }\n }\n if (elementsToAdd.length) {\n if (previousElement) {\n if (nextElement) {\n // There is a previous and next element - insertBefore the next element\n const docFrag = new DocumentFragment();\n docFrag.append(...elementsToAdd);\n targetForChildren.insertBefore(docFrag, nextElement);\n } else {\n // No next element - must be the last children\n targetForChildren.append(...elementsToAdd);\n }\n } else {\n // No previous element - must be the first children\n targetForChildren.prepend(...elementsToAdd);\n }\n }\n for (const removedNode of removedNodes) {\n const childElement = this.idToElement.get(removedNode);\n if (!childElement) {\n throw new Error(`Child element not found: ${removedNode}`);\n }\n this.elementToId.delete(childElement);\n this.idToElement.delete(removedNode);\n const targetForRemoval = getRemovalTarget(parent);\n targetForRemoval.removeChild(childElement);\n if (isHTMLElement(childElement, this.parentElement)) {\n // If child is capable of supporting children then remove any that exist\n this.removeChildElementIds(childElement);\n }\n }\n }\n\n private removeChildElementIds(parent: HTMLElement) {\n // If portal element, remove from portal element\n const portal = getChildrenTarget(parent);\n if (portal !== parent) {\n this.removeChildElementIds(portal as HTMLElement);\n }\n for (let i = 0; i < parent.childNodes.length; i++) {\n const child = parent.childNodes[i];\n const childId = this.elementToId.get(child as HTMLElement);\n if (!childId) {\n console.error(\"Inner child of removed element had no id\", child);\n } else {\n this.elementToId.delete(child);\n this.idToElement.delete(childId);\n }\n this.removeChildElementIds(child as HTMLElement);\n }\n }\n\n private handleSnapshot(message: NetworkedDOMV01SnapshotMessage) {\n // This websocket is successfully connected. Reset the backoff time.\n if (this.currentRoot) {\n this.currentRoot.remove();\n this.currentRoot = null;\n this.elementToId.clear();\n this.idToElement.clear();\n }\n\n // create a tree of DOM elements\n // NOTE: the MElement constructors are not executed during this stage\n const element = this.handleNewElement(message.snapshot);\n if (!element) {\n throw new Error(\"Snapshot element not created\");\n }\n if (!isHTMLElement(element, this.parentElement)) {\n throw new Error(\"Snapshot element is not an HTMLElement\");\n }\n this.currentRoot = element;\n // appending to the tree causes MElements to be constructed\n this.parentElement.append(element);\n }\n\n private handleAttributeChange(message: NetworkedDOMV01AttributeChangedDiff) {\n const { nodeId, attribute, newValue } = message;\n if (nodeId === undefined || nodeId === null) {\n console.warn(\"No nodeId in attributeChange message\");\n return;\n }\n const element = this.idToElement.get(nodeId);\n if (element) {\n if (isHTMLElement(element, this.parentElement)) {\n if (newValue === null) {\n element.removeAttribute(attribute);\n } else {\n setElementAttribute(element, attribute, newValue);\n }\n } else {\n console.error(\"Element is not an HTMLElement and cannot support attributes\", element);\n }\n } else {\n console.error(\"No element found for attributeChange message\");\n }\n }\n\n private handleNewElement(message: NetworkedDOMV01NodeDescription): Node | null {\n if (message.type === \"text\") {\n const { nodeId, text } = message;\n const textNode = document.createTextNode(\"\");\n textNode.textContent = text;\n this.idToElement.set(nodeId, textNode);\n this.elementToId.set(textNode, nodeId);\n return textNode;\n }\n const { tag, nodeId, attributes, children, text } = message;\n if (nodeId === undefined || nodeId === null) {\n console.warn(\"No nodeId in handleNewElement message\", message);\n return null;\n }\n if (this.idToElement.has(nodeId)) {\n console.error(\n \"Received nodeId to add that is already present\",\n nodeId,\n this.idToElement.get(nodeId),\n );\n }\n if (tag === \"#text\") {\n const textNode = document.createTextNode(\"\");\n textNode.textContent = text || null;\n this.idToElement.set(nodeId, textNode);\n this.elementToId.set(textNode, nodeId);\n return textNode;\n }\n\n let element;\n try {\n element = createElementWithSVGSupport(tag, this.options);\n } catch (e) {\n console.error(`Error creating element: (${tag})`, e);\n element = document.createElement(\"x-div\");\n }\n this.idToElement.set(nodeId, element);\n this.elementToId.set(element, nodeId);\n for (const key in attributes) {\n const value = attributes[key];\n setElementAttribute(element, key, value);\n }\n if (children) {\n for (const child of children) {\n const childElement = this.handleNewElement(child);\n if (childElement) {\n element.append(childElement);\n }\n }\n }\n return element;\n }\n}\n", "import {\n BufferReader,\n BufferWriter,\n decodeServerMessages,\n encodeClientMessage,\n getNetworkedDOMProtocolSubProtocol_v0_2SubversionOrThrow,\n networkedDOMProtocolSubProtocol_v0_2_Subversion,\n networkedDOMProtocolSubProtocol_v0_2_SubversionNumber,\n NetworkedDOMV02AttributesChangedDiff,\n NetworkedDOMV02ChangeHiddenFromDiff,\n NetworkedDOMV02ChildrenAddedDiff,\n NetworkedDOMV02ChildrenRemovedDiff,\n NetworkedDOMV02ClientMessage,\n NetworkedDOMV02DocumentTimeMessage,\n NetworkedDOMV02NodeDescription,\n NetworkedDOMV02PingMessage,\n NetworkedDOMV02RemoteEvent,\n NetworkedDOMV02ServerMessage,\n NetworkedDOMV02SnapshotMessage,\n NetworkedDOMV02TextChangedDiff,\n} from \"@mml-io/networked-dom-protocol\";\n\nimport {\n createElementWithSVGSupport,\n getChildrenTarget,\n getRemovalTarget,\n setElementAttribute,\n} from \"./ElementUtils\";\nimport {\n isHTMLElement,\n isText,\n NetworkedDOMWebsocketAdapter,\n NetworkedDOMWebsocketOptions,\n} from \"./NetworkedDOMWebsocket\";\n\n// This client uses a single connection id\nconst connectionId = 1;\n\n// If an element should not be visible to this client, it will be replaced with this tag and attributes will be stored ready to be applied if it is unhidden.\nconst hiddenTag = \"x-hidden\";\n\nexport class NetworkedDOMWebsocketV02Adapter implements NetworkedDOMWebsocketAdapter {\n private idToElement = new Map<number, Node>();\n private elementToId = new Map<Node, number>();\n private hiddenPlaceholderElements = new Map<\n number,\n {\n placeholder: Node;\n element: Node;\n }\n >();\n private currentRoot: HTMLElement | null = null;\n private batchMode = false;\n private batchMessages: Array<NetworkedDOMV02ServerMessage> = [];\n private readonly protocolSubversion: networkedDOMProtocolSubProtocol_v0_2_SubversionNumber;\n\n constructor(\n private websocket: WebSocket,\n private parentElement: HTMLElement,\n private connectedCallback: () => void,\n private timeCallback?: (time: number) => void,\n private options: NetworkedDOMWebsocketOptions = {},\n ) {\n this.websocket.binaryType = \"arraybuffer\";\n this.protocolSubversion = getNetworkedDOMProtocolSubProtocol_v0_2SubversionOrThrow(\n websocket.protocol as networkedDOMProtocolSubProtocol_v0_2_Subversion,\n );\n this.send({\n type: \"connectUsers\",\n connectionIds: [connectionId],\n connectionTokens: [this.options.connectionToken ?? null],\n });\n }\n\n public handleEvent(element: HTMLElement, event: CustomEvent<{ element: HTMLElement }>) {\n const nodeId = this.elementToId.get(element);\n if (nodeId === undefined || nodeId === null) {\n console.error(\"Element not found for event\", { nodeId, element, event });\n return;\n }\n\n const detailWithoutElement: Partial<typeof event.detail> = {\n ...event.detail,\n };\n delete detailWithoutElement.element;\n\n const remoteEvent: NetworkedDOMV02RemoteEvent = {\n type: \"event\",\n nodeId,\n connectionId,\n name: event.type,\n bubbles: event.bubbles,\n params: detailWithoutElement,\n };\n\n this.send(remoteEvent);\n }\n\n private send(message: NetworkedDOMV02ClientMessage) {\n const writer = new BufferWriter(256);\n encodeClientMessage(message, writer, this.protocolSubversion);\n this.websocket.send(writer.getBuffer());\n }\n\n public clearContents(): boolean {\n this.idToElement.clear();\n this.elementToId.clear();\n if (this.currentRoot) {\n this.currentRoot.remove();\n this.currentRoot = null;\n return true;\n }\n return false;\n }\n\n public receiveMessage(event: MessageEvent) {\n const reader = new BufferReader(new Uint8Array(event.data));\n const messages = decodeServerMessages(reader);\n for (const message of messages) {\n if (message.type === \"batchStart\") {\n // Need to wait for batchEnd before applying messages\n this.batchMode = true;\n } else if (message.type === \"batchEnd\") {\n // Apply all messages\n this.batchMode = false;\n for (const message of this.batchMessages) {\n this.applyMessage(message);\n }\n this.batchMessages = [];\n } else {\n if (this.batchMode) {\n this.batchMessages.push(message);\n } else {\n this.applyMessage(message);\n }\n }\n }\n }\n\n private applyMessage(message: NetworkedDOMV02ServerMessage) {\n switch (message.type) {\n case \"error\":\n console.error(\"Error from server\", message);\n break;\n case \"warning\":\n console.warn(\"Warning from server\", message);\n break;\n case \"snapshot\":\n this.handleSnapshot(message);\n this.connectedCallback();\n break;\n case \"attributesChanged\":\n this.handleAttributeChange(message);\n break;\n case \"documentTime\":\n this.handleDocumentTime(message);\n break;\n case \"childrenAdded\":\n this.handleChildrenAdded(message);\n break;\n case \"changeHiddenFrom\":\n this.handleChangeHiddenFrom(message);\n break;\n case \"changeVisibleTo\":\n // no-op for end user clients\n break;\n case \"childrenRemoved\":\n this.handleChildrenRemoved(message);\n break;\n case \"textChanged\":\n this.handleTextChanged(message);\n break;\n case \"ping\":\n this.handlePing(message);\n break;\n default:\n console.warn(\"unknown message type\", message);\n break;\n }\n }\n\n private handleTextChanged(message: NetworkedDOMV02TextChangedDiff) {\n const { nodeId, text } = message;\n\n if (nodeId === undefined || nodeId === null) {\n console.warn(\"No nodeId in textChanged message\");\n return;\n }\n const node = this.idToElement.get(nodeId);\n if (!node) {\n throw new Error(\"No node found for textChanged message\");\n }\n if (!isText(node, this.parentElement)) {\n throw new Error(\"Node for textChanged message is not a Text node\");\n }\n node.textContent = text;\n }\n\n private handleChangeHiddenFrom(message: NetworkedDOMV02ChangeHiddenFromDiff) {\n const { nodeId, addHiddenFrom, removeHiddenFrom } = message;\n const node = this.idToElement.get(nodeId);\n const hiddenElement = this.hiddenPlaceholderElements.get(nodeId);\n if (addHiddenFrom.length > 0 && addHiddenFrom.indexOf(connectionId) !== -1) {\n // This element is being hidden\n if (hiddenElement) {\n // This element is already hidden\n return;\n }\n if (!node) {\n throw new Error(\"No node found for changeHiddenFrom message\");\n }\n const parent = node.parentElement;\n if (!parent) {\n throw new Error(\"Node has no parent\");\n }\n const placeholder = document.createElement(hiddenTag);\n parent.replaceChild(placeholder, node);\n this.hiddenPlaceholderElements.set(nodeId, { placeholder, element: node });\n } else if (removeHiddenFrom.length > 0 && removeHiddenFrom.indexOf(connectionId) !== -1) {\n // This element is being unhidden\n if (!hiddenElement) {\n // This element is not hidden\n return;\n }\n const { placeholder, element } = hiddenElement;\n const parent = placeholder.parentElement;\n if (!parent) {\n throw new Error(\"Placeholder has no parent\");\n }\n parent.replaceChild(element, placeholder);\n this.hiddenPlaceholderElements.delete(nodeId);\n }\n }\n\n private handleChildrenAdded(message: NetworkedDOMV02ChildrenAddedDiff) {\n const { nodeId, addedNodes, previousNodeId } = message;\n if (nodeId === undefined || nodeId === null) {\n console.warn(\"No nodeId in childrenChanged message\");\n return;\n }\n let parent = this.idToElement.get(nodeId);\n if (!parent) {\n throw new Error(\"No parent found for childrenChanged message\");\n }\n\n const hiddenParent = this.hiddenPlaceholderElements.get(nodeId);\n if (hiddenParent) {\n // This element is hidden - add the children to the hidden element (not the placeholder)\n parent = hiddenParent.element;\n } else {\n if (!parent.isConnected) {\n console.error(\"Parent is not connected\", parent);\n }\n }\n if (!isHTMLElement(parent, this.parentElement)) {\n throw new Error(\"Parent is not an HTMLElement (that supports children)\");\n }\n\n const targetForChildren = getChildrenTarget(parent);\n\n let nextElement = null;\n let previousElement = null;\n if (previousNodeId) {\n previousElement = this.idToElement.get(previousNodeId);\n if (!previousElement) {\n throw new Error(\"No previous element found for childrenChanged message\");\n }\n nextElement = previousElement.nextSibling;\n }\n\n const elementsToAdd = [];\n for (const addedNode of addedNodes) {\n const childElement = this.handleNewElement(addedNode);\n if (childElement) {\n elementsToAdd.push(childElement);\n }\n }\n if (elementsToAdd.length) {\n if (previousElement) {\n if (nextElement) {\n // There is a previous and next element - insertBefore the next element\n const docFrag = new DocumentFragment();\n docFrag.append(...elementsToAdd);\n targetForChildren.insertBefore(docFrag, nextElement);\n } else {\n // No next element - must be the last children\n targetForChildren.append(...elementsToAdd);\n }\n } else {\n // No previous element - must be the first children\n targetForChildren.prepend(...elementsToAdd);\n }\n }\n }\n\n private handleChildrenRemoved(message: NetworkedDOMV02ChildrenRemovedDiff) {\n const { nodeId, removedNodes } = message;\n if (nodeId === undefined || nodeId === null) {\n console.warn(\"No nodeId in childrenChanged message\");\n return;\n }\n const parent = this.idToElement.get(nodeId);\n if (!parent) {\n throw new Error(\"No parent found for childrenChanged message\");\n }\n if (!parent.isConnected) {\n console.error(\"Parent is not connected\", parent);\n }\n if (!isHTMLElement(parent, this.parentElement)) {\n throw new Error(\"Parent is not an HTMLElement (that supports children)\");\n }\n\n for (const removedNode of removedNodes) {\n const childElement = this.idToElement.get(removedNode);\n if (!childElement) {\n throw new Error(`Child element not found: ${removedNode}`);\n }\n this.elementToId.delete(childElement);\n this.idToElement.delete(removedNode);\n this.hiddenPlaceholderElements.delete(removedNode);\n\n const targetForRemoval = getRemovalTarget(parent);\n\n targetForRemoval.removeChild(childElement);\n if (isHTMLElement(childElement, this.parentElement)) {\n // If child is capable of supporting children then remove any that exist\n this.removeChildElementIds(childElement);\n }\n }\n }\n\n private removeChildElementIds(parent: HTMLElement) {\n // If portal element, remove from portal element\n const portal = getChildrenTarget(parent);\n if (portal !== parent) {\n this.removeChildElementIds(portal as HTMLElement);\n }\n for (let i = 0; i < parent.childNodes.length; i++) {\n const child = parent.childNodes[i];\n const childId = this.elementToId.get(child as HTMLElement);\n if (!childId) {\n console.error(\"Inner child of removed element had no id\", child);\n } else {\n this.elementToId.delete(child);\n this.idToElement.delete(childId);\n this.hiddenPlaceholderElements.delete(childId);\n }\n this.removeChildElementIds(child as HTMLElement);\n }\n }\n\n private handleSnapshot(message: NetworkedDOMV02SnapshotMessage) {\n // This websocket is successfully connected. Reset the backoff time.\n if (this.currentRoot) {\n this.currentRoot.remove();\n this.currentRoot = null;\n this.elementToId.clear();\n this.idToElement.clear();\n }\n\n this.timeCallback?.(message.documentTime);\n\n // create a tree of DOM elements\n // NOTE: the MElement constructors are not executed during this stage\n const element = this.handleNewElement(message.snapshot);\n if (!element) {\n throw new Error(\"Snapshot element not created\");\n }\n if (!isHTMLElement(element, this.parentElement)) {\n throw new Error(\"Snapshot element is not an HTMLElement\");\n }\n this.currentRoot = element;\n // appending to the tree causes MElements to be constructed\n this.parentElement.append(element);\n }\n\n private handleDocumentTime(message: NetworkedDOMV02DocumentTimeMessage) {\n this.timeCallback?.(message.documentTime);\n }\n\n private handleAttributeChange(message: NetworkedDOMV02AttributesChangedDiff) {\n const { nodeId, attributes } = message;\n if (nodeId === undefined || nodeId === null) {\n console.warn(\"No nodeId in attributeChange message\");\n return;\n }\n let element = this.idToElement.get(nodeId);\n const hiddenElement = this.hiddenPlaceholderElements.get(nodeId);\n if (hiddenElement) {\n // This element is hidden - apply the attributes to the hidden element\n element = hiddenElement.element;\n }\n if (element) {\n if (isHTMLElement(element, this.parentElement)) {\n for (const [key, newValue] of attributes) {\n if (newValue === null) {\n element.removeAttribute(key);\n } else {\n setElementAttribute(element, key, newValue);\n }\n }\n } else {\n console.error(\"Element is not an HTMLElement and cannot support attributes\", element);\n }\n } else {\n console.error(\"No element found for attributeChange message\");\n }\n }\n\n private handleNewElement(message: NetworkedDOMV02NodeDescription): Node | null {\n if (message.type === \"text\") {\n const { nodeId, text } = message;\n const textNode = document.createTextNode(\"\");\n textNode.textContent = text;\n this.idToElement.set(nodeId, textNode);\n this.elementToId.set(textNode, nodeId);\n return textNode;\n }\n const { tag, nodeId, attributes, children, text, hiddenFrom } = message;\n if (this.idToElement.has(nodeId)) {\n console.error(\n \"Received nodeId to add that is already present\",\n nodeId,\n this.idToElement.get(nodeId),\n );\n return null;\n }\n\n if (tag === \"#text\") {\n const textNode = document.createTextNode(\"\");\n textNode.textContent = text || null;\n this.idToElement.set(nodeId, textNode);\n this.elementToId.set(textNode, nodeId);\n return textNode;\n }\n\n let element: Element;\n try {\n element = createElementWithSVGSupport(tag, this.options);\n } catch (e) {\n console.error(`Error creating element: (${tag})`, e);\n element = document.createElement(\"x-div\");\n }\n for (const [key, value] of attributes) {\n if (value !== null) {\n setElementAttribute(element, key, value);\n }\n }\n if (children) {\n for (const child of children) {\n const childElement = this.handleNewElement(child);\n if (childElement) {\n element.append(childElement);\n }\n }\n }\n\n if (hiddenFrom && hiddenFrom.length > 0 && hiddenFrom.indexOf(connectionId) !== -1) {\n // This element is hidden - create a placeholder that will be in the DOM to maintain structure, but keep the underlying element hidden\n const placeholder = document.createElement(hiddenTag);\n this.idToElement.set(nodeId, placeholder);\n this.elementToId.set(placeholder, nodeId);\n this.hiddenPlaceholderElements.set(nodeId, { placeholder, element });\n return placeholder;\n } else {\n this.idToElement.set(nodeId, element);\n this.elementToId.set(element, nodeId);\n return element;\n }\n }\n\n private handlePing(message: NetworkedDOMV02PingMessage) {\n this.timeCallback?.(message.documentTime);\n this.send({\n type: \"pong\",\n pong: message.ping,\n });\n }\n}\n", "import { NetworkedDOMWebsocket } from \"@mml-io/networked-dom-web\";\n\nconst thisScript = document.currentScript as HTMLScriptElement;\nconst scriptUrl = new URL(thisScript.src);\n\n(function () {\n const url = scriptUrl.searchParams.get(\"url\");\n if (!url) {\n console.error(\"url not set\");\n return;\n }\n window.addEventListener(\"load\", () => {\n let overriddenHandler: ((element: HTMLElement, event: CustomEvent) => void) | null = null;\n const eventHandler = (element: HTMLElement, event: CustomEvent) => {\n if (!overriddenHandler) {\n throw new Error(\"overriddenHandler not set\");\n }\n overriddenHandler(element, event);\n };\n const remoteDocumentHolder = document.createElement(\"div\");\n document.body.append(remoteDocumentHolder);\n\n remoteDocumentHolder.addEventListener(\"click\", (event: Event) => {\n eventHandler(event.target as HTMLElement, event as CustomEvent);\n return false;\n });\n\n const websocket = new NetworkedDOMWebsocket(\n url,\n NetworkedDOMWebsocket.createWebSocket,\n remoteDocumentHolder,\n );\n overriddenHandler = (element: HTMLElement, event: CustomEvent) => {\n websocket.handleEvent(element, event);\n };\n });\n})();\n"],
5
+ "mappings": "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,UAAU,WAAW,IAAI;EACnC;AACF;AEzGA,IAAM,yBAAyB,oBAAI,IAAI,CAAC,iBAAiB,UAAU,QAAQ,CAAC;AAE5E,IAAM,+BAA+B,IAAI;EACvC;IACE;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;;;EAGF,EAAE,IAAI,CAAC,OAAO,CAAC,GAAG,YAAY,GAAG,EAAE,CAAC;AACtC;AAEA,IAAM,2BAA2B,IAAI;EACnC;IACE;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;EACF,EAAE,IAAI,CAAC,SAAS,CAAC,KAAK,YAAY,GAAG,IAAI,CAAC;AAC5C;AAKO,SAAS,mBAAmB,UAA0B;AAC3D,QAAM,WAAW,yBAAyB,IAAI,SAAS,YAAY,CAAC;AACpE,MAAI,UAAU;AACZ,WAAO;EACT;AACA,SAAO;AACT;AAKO,SAAS,4BACd,KACA,UAAwC,CAAC,GAChC;AACT,MAAI,cAAc,IAAI,YAAY;AAElC,MAAI,uBAAuB,IAAI,YAAY,YAAY,CAAC,GAAG;AACzD,YAAQ,MAAM,mBAAmB,WAAW;AAC5C,kBAAc,QAAQ,uBAAuB,QAAQ,uBAAuB,MAAM,KAAK,GAAG;EAC5F;AAEA,MAAI;AACJ,MAAI,QAAQ,kBAAkB;AAC5B,oBAAgB,6BAA6B,IAAI,WAAW;EAC9D;AAEA,MAAI,eAAe;AACjB,kBAAc;AACd,UAAM,QAA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",
6
6
  "names": ["c", "nodeId", "text", "message"]
7
7
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mml-io/networked-dom-web-client",
3
- "version": "0.20.0",
3
+ "version": "0.21.0",
4
4
  "publishConfig": {
5
5
  "access": "public"
6
6
  },
@@ -17,7 +17,7 @@
17
17
  "lint-fix": "eslint \"./**/*.{js,jsx,ts,tsx}\" --fix"
18
18
  },
19
19
  "dependencies": {
20
- "@mml-io/networked-dom-web": "^0.20.0"
20
+ "@mml-io/networked-dom-web": "^0.21.0"
21
21
  },
22
- "gitHead": "c59b905d9883fb39200d7b73c521b6a759cd2eee"
22
+ "gitHead": "7763fa330ffdc27b578d0cc4f757506630076271"
23
23
  }