@mml-io/networked-dom-web-client 0.25.0 → 0.26.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 +388 -255
- package/build/index.js.map +4 -4
- package/package.json +3 -3
package/build/index.js
CHANGED
|
@@ -586,51 +586,91 @@ function encodeClientMessage(message, writer, protocolSubversion) {
|
|
|
586
586
|
}
|
|
587
587
|
|
|
588
588
|
// ../networked-dom-web/build/index.js
|
|
589
|
-
var
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
589
|
+
var VIRTUAL_ELEMENT_BRAND = /* @__PURE__ */ Symbol.for("mml-virtual-element");
|
|
590
|
+
var VIRTUAL_TEXT_BRAND = /* @__PURE__ */ Symbol.for("mml-virtual-text");
|
|
591
|
+
function isElementLike(node) {
|
|
592
|
+
return typeof node.setAttribute === "function";
|
|
593
|
+
}
|
|
594
|
+
function isPortalElement(element) {
|
|
595
|
+
return typeof element.getPortalElement === "function";
|
|
596
|
+
}
|
|
597
|
+
var _DOMSanitizer = class _DOMSanitizer2 {
|
|
598
|
+
/**
|
|
599
|
+
* Returns true if a tag with the given name should be stripped of all
|
|
600
|
+
* content and attributes during sanitisation.
|
|
601
|
+
*/
|
|
602
|
+
static isBlockedTag(tagName) {
|
|
603
|
+
return _DOMSanitizer2.BLOCKED_TAGS.has(tagName.toLowerCase());
|
|
604
|
+
}
|
|
605
|
+
/**
|
|
606
|
+
* Given a tag name and sanitisation options, returns the sanitised tag name.
|
|
607
|
+
* Non-prefixed tags are renamed (e.g. "div" → "x-div"). Returns null for
|
|
608
|
+
* blocked tags that should be skipped entirely.
|
|
609
|
+
*/
|
|
610
|
+
static sanitiseTagName(tagName, options) {
|
|
611
|
+
const tag = tagName.toLowerCase();
|
|
612
|
+
if (_DOMSanitizer2.isBlockedTag(tag)) {
|
|
613
|
+
return null;
|
|
597
614
|
}
|
|
598
|
-
if (
|
|
599
|
-
|
|
600
|
-
const tag = node.nodeName.toLowerCase();
|
|
601
|
-
if (!tag.startsWith(options.tagPrefix.toLowerCase())) {
|
|
602
|
-
node = _DOMSanitizer.replaceNodeTagName(
|
|
603
|
-
node,
|
|
604
|
-
options.replacementTagPrefix ? options.replacementTagPrefix + tag : `x-${tag}`
|
|
605
|
-
);
|
|
606
|
-
}
|
|
607
|
-
}
|
|
615
|
+
if (options.tagPrefix && !tag.startsWith(options.tagPrefix.toLowerCase())) {
|
|
616
|
+
return (options.replacementTagPrefix ?? "x-") + tag;
|
|
608
617
|
}
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
618
|
+
return tag;
|
|
619
|
+
}
|
|
620
|
+
/**
|
|
621
|
+
* Sanitises a DOM node in-place. When tag replacement occurs (via tagPrefix option),
|
|
622
|
+
* the returned node may be a different object than the input node.
|
|
623
|
+
*/
|
|
624
|
+
static sanitise(node, options = {}, doc) {
|
|
625
|
+
if (_DOMSanitizer2.isBlockedTag(node.nodeName)) {
|
|
626
|
+
if (isElementLike(node)) {
|
|
627
|
+
node.innerHTML = "";
|
|
628
|
+
_DOMSanitizer2.stripAllAttributes(node);
|
|
629
|
+
}
|
|
612
630
|
} else {
|
|
613
|
-
if (node
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
631
|
+
if (isElementLike(node)) {
|
|
632
|
+
let element = node;
|
|
633
|
+
for (const attr of element.getAttributeNames()) {
|
|
634
|
+
if (!_DOMSanitizer2.IsValidAttributeName(attr)) {
|
|
635
|
+
element.removeAttribute(attr);
|
|
636
|
+
}
|
|
637
|
+
}
|
|
638
|
+
if (options.tagPrefix) {
|
|
639
|
+
const tag = element.nodeName.toLowerCase();
|
|
640
|
+
if (!tag.startsWith(options.tagPrefix.toLowerCase())) {
|
|
641
|
+
element = _DOMSanitizer2.replaceNodeTagName(
|
|
642
|
+
element,
|
|
643
|
+
(options.replacementTagPrefix ?? "x-") + tag,
|
|
644
|
+
doc
|
|
645
|
+
);
|
|
646
|
+
node = element;
|
|
647
|
+
}
|
|
648
|
+
}
|
|
649
|
+
for (const attr of element.getAttributeNames()) {
|
|
650
|
+
if (!_DOMSanitizer2.shouldAcceptAttribute(attr)) {
|
|
651
|
+
element.removeAttribute(attr);
|
|
617
652
|
}
|
|
618
653
|
}
|
|
619
654
|
}
|
|
620
655
|
for (let i = 0; i < node.childNodes.length; i++) {
|
|
621
|
-
|
|
656
|
+
_DOMSanitizer2.sanitise(node.childNodes[i], options, doc);
|
|
622
657
|
}
|
|
623
658
|
}
|
|
624
659
|
return node;
|
|
625
660
|
}
|
|
626
|
-
static replaceNodeTagName(node, newTagName) {
|
|
661
|
+
static replaceNodeTagName(node, newTagName, doc) {
|
|
627
662
|
var _a;
|
|
628
|
-
|
|
629
|
-
|
|
663
|
+
if (!doc && typeof document === "undefined") {
|
|
664
|
+
throw new Error(
|
|
665
|
+
"DOMSanitizer.replaceNodeTagName requires a document factory (IDocumentFactory) in non-browser environments"
|
|
666
|
+
);
|
|
667
|
+
}
|
|
668
|
+
const docFactory = doc ?? document;
|
|
669
|
+
const replacementNode = docFactory.createElement(newTagName);
|
|
630
670
|
while (node.firstChild) {
|
|
631
671
|
replacementNode.appendChild(node.firstChild);
|
|
632
672
|
}
|
|
633
|
-
for (index = node.attributes.length - 1; index >= 0; --index) {
|
|
673
|
+
for (let index = node.attributes.length - 1; index >= 0; --index) {
|
|
634
674
|
replacementNode.setAttribute(node.attributes[index].name, node.attributes[index].value);
|
|
635
675
|
}
|
|
636
676
|
(_a = node.parentNode) == null ? void 0 : _a.replaceChild(replacementNode, node);
|
|
@@ -651,25 +691,27 @@ var DOMSanitizer = class _DOMSanitizer {
|
|
|
651
691
|
}
|
|
652
692
|
static IsValidAttributeName(characters) {
|
|
653
693
|
const c = characters[0];
|
|
654
|
-
if (!(
|
|
694
|
+
if (!(_DOMSanitizer2.IsASCIIAlpha(c) || c === ":" || c === "_")) {
|
|
655
695
|
return false;
|
|
656
696
|
}
|
|
657
697
|
for (let i = 1; i < characters.length; i++) {
|
|
658
698
|
const c2 = characters[i];
|
|
659
|
-
if (!(
|
|
699
|
+
if (!(_DOMSanitizer2.IsASCIIDigit(c2) || _DOMSanitizer2.IsASCIIAlpha(c2) || c2 === ":" || c2 === "_" || c2 === "-" || c2 === ".")) {
|
|
660
700
|
return false;
|
|
661
701
|
}
|
|
662
702
|
}
|
|
663
703
|
return true;
|
|
664
704
|
}
|
|
665
705
|
static shouldAcceptAttribute(attribute) {
|
|
666
|
-
if (!
|
|
706
|
+
if (!_DOMSanitizer2.IsValidAttributeName(attribute)) {
|
|
667
707
|
console.warn("Invalid attribute name", attribute);
|
|
668
708
|
return false;
|
|
669
709
|
}
|
|
670
710
|
return !attribute.startsWith("on");
|
|
671
711
|
}
|
|
672
712
|
};
|
|
713
|
+
_DOMSanitizer.BLOCKED_TAGS = /* @__PURE__ */ new Set(["script", "object", "iframe"]);
|
|
714
|
+
var DOMSanitizer = _DOMSanitizer;
|
|
673
715
|
var ALWAYS_DISALLOWED_TAGS = /* @__PURE__ */ new Set(["foreignobject", "iframe", "script"]);
|
|
674
716
|
var SVG_TAG_NAMES_ADJUSTMENT_MAP = new Map(
|
|
675
717
|
[
|
|
@@ -793,7 +835,13 @@ function remapAttributeName(attrName) {
|
|
|
793
835
|
}
|
|
794
836
|
return attrName;
|
|
795
837
|
}
|
|
796
|
-
function createElementWithSVGSupport(tag, options = {}) {
|
|
838
|
+
function createElementWithSVGSupport(tag, options = {}, doc) {
|
|
839
|
+
if (!doc && typeof document === "undefined") {
|
|
840
|
+
throw new Error(
|
|
841
|
+
"createElementWithSVGSupport requires a document factory (IDocumentFactory) in non-browser environments"
|
|
842
|
+
);
|
|
843
|
+
}
|
|
844
|
+
const docFactory = doc ?? document;
|
|
797
845
|
let filteredTag = tag.toLowerCase();
|
|
798
846
|
if (ALWAYS_DISALLOWED_TAGS.has(filteredTag.toLowerCase())) {
|
|
799
847
|
console.error("Disallowing tag", filteredTag);
|
|
@@ -806,14 +854,17 @@ function createElementWithSVGSupport(tag, options = {}) {
|
|
|
806
854
|
if (svgTagMapping) {
|
|
807
855
|
filteredTag = svgTagMapping;
|
|
808
856
|
const xmlns = "http://www.w3.org/2000/svg";
|
|
809
|
-
|
|
857
|
+
if (docFactory.createElementNS) {
|
|
858
|
+
return docFactory.createElementNS(xmlns, filteredTag);
|
|
859
|
+
}
|
|
860
|
+
return docFactory.createElement(filteredTag);
|
|
810
861
|
} else {
|
|
811
862
|
if (options.tagPrefix) {
|
|
812
863
|
if (!tag.toLowerCase().startsWith(options.tagPrefix.toLowerCase())) {
|
|
813
864
|
filteredTag = options.replacementTagPrefix ? options.replacementTagPrefix + tag : `x-${tag}`;
|
|
814
865
|
}
|
|
815
866
|
}
|
|
816
|
-
return
|
|
867
|
+
return docFactory.createElement(filteredTag);
|
|
817
868
|
}
|
|
818
869
|
}
|
|
819
870
|
function setElementAttribute(element, key, value) {
|
|
@@ -823,21 +874,58 @@ function setElementAttribute(element, key, value) {
|
|
|
823
874
|
}
|
|
824
875
|
}
|
|
825
876
|
function getChildrenTarget(parent) {
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
targetForChildren = parent.getPortalElement();
|
|
877
|
+
if (isPortalElement(parent)) {
|
|
878
|
+
return parent.getPortalElement();
|
|
829
879
|
}
|
|
830
|
-
return
|
|
880
|
+
return parent;
|
|
831
881
|
}
|
|
832
882
|
function getRemovalTarget(parent) {
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
targetForRemoval = parent.getPortalElement();
|
|
883
|
+
if (isPortalElement(parent)) {
|
|
884
|
+
return parent.getPortalElement();
|
|
836
885
|
}
|
|
837
|
-
return
|
|
886
|
+
return parent;
|
|
838
887
|
}
|
|
839
|
-
|
|
840
|
-
|
|
888
|
+
function resolveChildFactory(parentNode, elementFactoryOverride) {
|
|
889
|
+
var _a;
|
|
890
|
+
if (isElementLike(parentNode) && isPortalElement(parentNode)) {
|
|
891
|
+
const portalFactory = (_a = parentNode.getPortalDocumentFactory) == null ? void 0 : _a.call(parentNode);
|
|
892
|
+
if (portalFactory) {
|
|
893
|
+
return portalFactory;
|
|
894
|
+
}
|
|
895
|
+
}
|
|
896
|
+
return elementFactoryOverride.get(parentNode);
|
|
897
|
+
}
|
|
898
|
+
function resolvePortalChildFactory(element, currentFactory) {
|
|
899
|
+
var _a;
|
|
900
|
+
if (isPortalElement(element)) {
|
|
901
|
+
const portalFactory = (_a = element.getPortalDocumentFactory) == null ? void 0 : _a.call(element);
|
|
902
|
+
if (portalFactory) {
|
|
903
|
+
return { childFactory: portalFactory, usingPortalFactory: true };
|
|
904
|
+
}
|
|
905
|
+
}
|
|
906
|
+
return { childFactory: currentFactory, usingPortalFactory: false };
|
|
907
|
+
}
|
|
908
|
+
function recordFactoryOverride(element, factory, defaultFactory, elementFactoryOverride) {
|
|
909
|
+
if (factory !== defaultFactory) {
|
|
910
|
+
elementFactoryOverride.set(element, factory);
|
|
911
|
+
}
|
|
912
|
+
}
|
|
913
|
+
function flushPendingPortalChildren(pendingPortalChildren) {
|
|
914
|
+
for (const [portalParent, children] of pendingPortalChildren) {
|
|
915
|
+
const target = getChildrenTarget(portalParent);
|
|
916
|
+
for (const child of children) {
|
|
917
|
+
target.appendChild(child);
|
|
918
|
+
}
|
|
919
|
+
}
|
|
920
|
+
pendingPortalChildren.clear();
|
|
921
|
+
}
|
|
922
|
+
function bufferPortalChild(pendingPortalChildren, portalParent, child) {
|
|
923
|
+
const pending = pendingPortalChildren.get(portalParent) ?? [];
|
|
924
|
+
pending.push(child);
|
|
925
|
+
pendingPortalChildren.set(portalParent, pending);
|
|
926
|
+
}
|
|
927
|
+
var NetworkedDOMWebsocketAdapterBase = class {
|
|
928
|
+
constructor(websocket, parentElement, connectedCallback, timeCallback, options = {}, doc) {
|
|
841
929
|
this.websocket = websocket;
|
|
842
930
|
this.parentElement = parentElement;
|
|
843
931
|
this.connectedCallback = connectedCallback;
|
|
@@ -846,7 +934,117 @@ var NetworkedDOMWebsocketV01Adapter = class {
|
|
|
846
934
|
this.idToElement = /* @__PURE__ */ new Map();
|
|
847
935
|
this.elementToId = /* @__PURE__ */ new Map();
|
|
848
936
|
this.currentRoot = null;
|
|
937
|
+
this.pendingPortalChildren = /* @__PURE__ */ new Map();
|
|
938
|
+
this.elementFactoryOverride = /* @__PURE__ */ new Map();
|
|
849
939
|
this.websocket.binaryType = "arraybuffer";
|
|
940
|
+
if (!doc && typeof document === "undefined") {
|
|
941
|
+
throw new Error(
|
|
942
|
+
"NetworkedDOMWebsocketAdapter requires a document factory (IDocumentFactory) in non-browser environments"
|
|
943
|
+
);
|
|
944
|
+
}
|
|
945
|
+
this.docFactory = doc ?? document;
|
|
946
|
+
}
|
|
947
|
+
clearContents() {
|
|
948
|
+
this.idToElement.clear();
|
|
949
|
+
this.elementToId.clear();
|
|
950
|
+
this.elementFactoryOverride.clear();
|
|
951
|
+
this.pendingPortalChildren.clear();
|
|
952
|
+
if (this.currentRoot) {
|
|
953
|
+
this.currentRoot.remove();
|
|
954
|
+
this.currentRoot = null;
|
|
955
|
+
return true;
|
|
956
|
+
}
|
|
957
|
+
return false;
|
|
958
|
+
}
|
|
959
|
+
/**
|
|
960
|
+
* Creates a text node, registers it in the id maps, and returns it.
|
|
961
|
+
*/
|
|
962
|
+
createTextNode(nodeId, text, factory) {
|
|
963
|
+
const textNode = factory.createTextNode("");
|
|
964
|
+
textNode.textContent = text;
|
|
965
|
+
this.idToElement.set(nodeId, textNode);
|
|
966
|
+
this.elementToId.set(textNode, nodeId);
|
|
967
|
+
return textNode;
|
|
968
|
+
}
|
|
969
|
+
/**
|
|
970
|
+
* Inserts elements into the correct position within a parent, using
|
|
971
|
+
* previousElement/nextElement for positioning. Creates a DocumentFragment
|
|
972
|
+
* when inserting before a reference node.
|
|
973
|
+
*/
|
|
974
|
+
insertElements(targetForChildren, elementsToAdd, previousElement, nextElement, factory) {
|
|
975
|
+
if (elementsToAdd.length === 0) return;
|
|
976
|
+
if (previousElement) {
|
|
977
|
+
if (nextElement) {
|
|
978
|
+
const docFrag = factory.createDocumentFragment();
|
|
979
|
+
docFrag.append(...elementsToAdd);
|
|
980
|
+
targetForChildren.insertBefore(docFrag, nextElement);
|
|
981
|
+
} else {
|
|
982
|
+
targetForChildren.append(...elementsToAdd);
|
|
983
|
+
}
|
|
984
|
+
} else {
|
|
985
|
+
targetForChildren.prepend(...elementsToAdd);
|
|
986
|
+
}
|
|
987
|
+
}
|
|
988
|
+
/**
|
|
989
|
+
* Recursively removes element-to-id mappings for all descendants of a parent.
|
|
990
|
+
* V02 overrides this to also handle hidden placeholder elements.
|
|
991
|
+
*/
|
|
992
|
+
removeChildElementIds(parent) {
|
|
993
|
+
if (isElementLike(parent)) {
|
|
994
|
+
const portal = getChildrenTarget(parent);
|
|
995
|
+
if (portal !== parent) {
|
|
996
|
+
this.removeChildElementIds(portal);
|
|
997
|
+
}
|
|
998
|
+
}
|
|
999
|
+
for (let i = 0; i < parent.childNodes.length; i++) {
|
|
1000
|
+
const child = parent.childNodes[i];
|
|
1001
|
+
const childId = this.elementToId.get(child);
|
|
1002
|
+
if (!childId) {
|
|
1003
|
+
this.handleUnregisteredChild(child);
|
|
1004
|
+
} else {
|
|
1005
|
+
this.elementToId.delete(child);
|
|
1006
|
+
this.idToElement.delete(childId);
|
|
1007
|
+
this.elementFactoryOverride.delete(child);
|
|
1008
|
+
}
|
|
1009
|
+
this.removeChildElementIds(child);
|
|
1010
|
+
}
|
|
1011
|
+
}
|
|
1012
|
+
/**
|
|
1013
|
+
* Called during removeChildElementIds when a child has no registered id.
|
|
1014
|
+
* V01 logs an error. V02 overrides to check for placeholder elements.
|
|
1015
|
+
*/
|
|
1016
|
+
handleUnregisteredChild(child) {
|
|
1017
|
+
console.error("Inner child of removed element had no id", child);
|
|
1018
|
+
}
|
|
1019
|
+
/**
|
|
1020
|
+
* Resets state and applies a snapshot element to the parent.
|
|
1021
|
+
* Appending to the tree triggers MElement connectedCallbacks (which set up portals),
|
|
1022
|
+
* then pending portal children are flushed.
|
|
1023
|
+
*/
|
|
1024
|
+
resetAndApplySnapshot(element) {
|
|
1025
|
+
if (this.currentRoot) {
|
|
1026
|
+
this.removeChildElementIds(this.currentRoot);
|
|
1027
|
+
const rootId = this.elementToId.get(this.currentRoot);
|
|
1028
|
+
if (rootId !== void 0) {
|
|
1029
|
+
this.elementToId.delete(this.currentRoot);
|
|
1030
|
+
this.idToElement.delete(rootId);
|
|
1031
|
+
this.elementFactoryOverride.delete(this.currentRoot);
|
|
1032
|
+
}
|
|
1033
|
+
this.currentRoot.remove();
|
|
1034
|
+
this.currentRoot = null;
|
|
1035
|
+
this.pendingPortalChildren.clear();
|
|
1036
|
+
}
|
|
1037
|
+
if (!isHTMLElement(element, this.parentElement)) {
|
|
1038
|
+
throw new Error("Snapshot element is not an HTMLElement");
|
|
1039
|
+
}
|
|
1040
|
+
this.currentRoot = element;
|
|
1041
|
+
this.parentElement.append(element);
|
|
1042
|
+
flushPendingPortalChildren(this.pendingPortalChildren);
|
|
1043
|
+
}
|
|
1044
|
+
};
|
|
1045
|
+
var NetworkedDOMWebsocketV01Adapter = class extends NetworkedDOMWebsocketAdapterBase {
|
|
1046
|
+
constructor(websocket, parentElement, connectedCallback, timeCallback, options = {}, doc) {
|
|
1047
|
+
super(websocket, parentElement, connectedCallback, timeCallback, options, doc);
|
|
850
1048
|
}
|
|
851
1049
|
handleEvent(element, event) {
|
|
852
1050
|
const nodeId = this.elementToId.get(element);
|
|
@@ -869,16 +1067,6 @@ var NetworkedDOMWebsocketV01Adapter = class {
|
|
|
869
1067
|
send(fromClientMessage) {
|
|
870
1068
|
this.websocket.send(JSON.stringify(fromClientMessage));
|
|
871
1069
|
}
|
|
872
|
-
clearContents() {
|
|
873
|
-
this.idToElement.clear();
|
|
874
|
-
this.elementToId.clear();
|
|
875
|
-
if (this.currentRoot) {
|
|
876
|
-
this.currentRoot.remove();
|
|
877
|
-
this.currentRoot = null;
|
|
878
|
-
return true;
|
|
879
|
-
}
|
|
880
|
-
return false;
|
|
881
|
-
}
|
|
882
1070
|
receiveMessage(event) {
|
|
883
1071
|
try {
|
|
884
1072
|
const messages = JSON.parse(event.data);
|
|
@@ -950,14 +1138,15 @@ var NetworkedDOMWebsocketV01Adapter = class {
|
|
|
950
1138
|
console.warn("No nodeId in childrenChanged message");
|
|
951
1139
|
return;
|
|
952
1140
|
}
|
|
953
|
-
const
|
|
954
|
-
if (!
|
|
1141
|
+
const parentNode = this.idToElement.get(nodeId);
|
|
1142
|
+
if (!parentNode) {
|
|
955
1143
|
throw new Error("No parent found for childrenChanged message");
|
|
956
1144
|
}
|
|
957
|
-
if (!isHTMLElement(
|
|
1145
|
+
if (!isHTMLElement(parentNode, this.parentElement)) {
|
|
958
1146
|
throw new Error("Parent is not an HTMLElement (that supports children)");
|
|
959
1147
|
}
|
|
960
|
-
const
|
|
1148
|
+
const childFactory = resolveChildFactory(parentNode, this.elementFactoryOverride);
|
|
1149
|
+
const targetForChildren = getChildrenTarget(parentNode);
|
|
961
1150
|
let nextElement = null;
|
|
962
1151
|
let previousElement = null;
|
|
963
1152
|
if (previousNodeId) {
|
|
@@ -969,23 +1158,20 @@ var NetworkedDOMWebsocketV01Adapter = class {
|
|
|
969
1158
|
}
|
|
970
1159
|
const elementsToAdd = [];
|
|
971
1160
|
for (const addedNode of addedNodes) {
|
|
972
|
-
const childElement = this.handleNewElement(addedNode);
|
|
1161
|
+
const childElement = this.handleNewElement(addedNode, childFactory);
|
|
973
1162
|
if (childElement) {
|
|
974
1163
|
elementsToAdd.push(childElement);
|
|
975
1164
|
}
|
|
976
1165
|
}
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
} else {
|
|
987
|
-
targetForChildren.prepend(...elementsToAdd);
|
|
988
|
-
}
|
|
1166
|
+
this.insertElements(
|
|
1167
|
+
targetForChildren,
|
|
1168
|
+
elementsToAdd,
|
|
1169
|
+
previousElement,
|
|
1170
|
+
nextElement,
|
|
1171
|
+
childFactory ?? this.docFactory
|
|
1172
|
+
);
|
|
1173
|
+
if (this.pendingPortalChildren.size > 0) {
|
|
1174
|
+
flushPendingPortalChildren(this.pendingPortalChildren);
|
|
989
1175
|
}
|
|
990
1176
|
for (const removedNode of removedNodes) {
|
|
991
1177
|
const childElement = this.idToElement.get(removedNode);
|
|
@@ -994,46 +1180,19 @@ var NetworkedDOMWebsocketV01Adapter = class {
|
|
|
994
1180
|
}
|
|
995
1181
|
this.elementToId.delete(childElement);
|
|
996
1182
|
this.idToElement.delete(removedNode);
|
|
997
|
-
const targetForRemoval = getRemovalTarget(
|
|
1183
|
+
const targetForRemoval = getRemovalTarget(parentNode);
|
|
998
1184
|
targetForRemoval.removeChild(childElement);
|
|
999
1185
|
if (isHTMLElement(childElement, this.parentElement)) {
|
|
1000
1186
|
this.removeChildElementIds(childElement);
|
|
1001
1187
|
}
|
|
1002
1188
|
}
|
|
1003
1189
|
}
|
|
1004
|
-
removeChildElementIds(parent) {
|
|
1005
|
-
const portal = getChildrenTarget(parent);
|
|
1006
|
-
if (portal !== parent) {
|
|
1007
|
-
this.removeChildElementIds(portal);
|
|
1008
|
-
}
|
|
1009
|
-
for (let i = 0; i < parent.childNodes.length; i++) {
|
|
1010
|
-
const child = parent.childNodes[i];
|
|
1011
|
-
const childId = this.elementToId.get(child);
|
|
1012
|
-
if (!childId) {
|
|
1013
|
-
console.error("Inner child of removed element had no id", child);
|
|
1014
|
-
} else {
|
|
1015
|
-
this.elementToId.delete(child);
|
|
1016
|
-
this.idToElement.delete(childId);
|
|
1017
|
-
}
|
|
1018
|
-
this.removeChildElementIds(child);
|
|
1019
|
-
}
|
|
1020
|
-
}
|
|
1021
1190
|
handleSnapshot(message) {
|
|
1022
|
-
if (this.currentRoot) {
|
|
1023
|
-
this.currentRoot.remove();
|
|
1024
|
-
this.currentRoot = null;
|
|
1025
|
-
this.elementToId.clear();
|
|
1026
|
-
this.idToElement.clear();
|
|
1027
|
-
}
|
|
1028
1191
|
const element = this.handleNewElement(message.snapshot);
|
|
1029
1192
|
if (!element) {
|
|
1030
1193
|
throw new Error("Snapshot element not created");
|
|
1031
1194
|
}
|
|
1032
|
-
|
|
1033
|
-
throw new Error("Snapshot element is not an HTMLElement");
|
|
1034
|
-
}
|
|
1035
|
-
this.currentRoot = element;
|
|
1036
|
-
this.parentElement.append(element);
|
|
1195
|
+
this.resetAndApplySnapshot(element);
|
|
1037
1196
|
}
|
|
1038
1197
|
handleAttributeChange(message) {
|
|
1039
1198
|
const { nodeId, attribute, newValue } = message;
|
|
@@ -1041,29 +1200,25 @@ var NetworkedDOMWebsocketV01Adapter = class {
|
|
|
1041
1200
|
console.warn("No nodeId in attributeChange message");
|
|
1042
1201
|
return;
|
|
1043
1202
|
}
|
|
1044
|
-
const
|
|
1045
|
-
if (
|
|
1046
|
-
if (isHTMLElement(
|
|
1203
|
+
const node = this.idToElement.get(nodeId);
|
|
1204
|
+
if (node) {
|
|
1205
|
+
if (isHTMLElement(node, this.parentElement)) {
|
|
1047
1206
|
if (newValue === null) {
|
|
1048
|
-
|
|
1207
|
+
node.removeAttribute(attribute);
|
|
1049
1208
|
} else {
|
|
1050
|
-
setElementAttribute(
|
|
1209
|
+
setElementAttribute(node, attribute, newValue);
|
|
1051
1210
|
}
|
|
1052
1211
|
} else {
|
|
1053
|
-
console.error("Element is not an HTMLElement and cannot support attributes",
|
|
1212
|
+
console.error("Element is not an HTMLElement and cannot support attributes", node);
|
|
1054
1213
|
}
|
|
1055
1214
|
} else {
|
|
1056
1215
|
console.error("No element found for attributeChange message");
|
|
1057
1216
|
}
|
|
1058
1217
|
}
|
|
1059
|
-
handleNewElement(message) {
|
|
1218
|
+
handleNewElement(message, factoryOverride) {
|
|
1219
|
+
const factory = factoryOverride ?? this.docFactory;
|
|
1060
1220
|
if (message.type === "text") {
|
|
1061
|
-
|
|
1062
|
-
const textNode = document.createTextNode("");
|
|
1063
|
-
textNode.textContent = text2;
|
|
1064
|
-
this.idToElement.set(nodeId2, textNode);
|
|
1065
|
-
this.elementToId.set(textNode, nodeId2);
|
|
1066
|
-
return textNode;
|
|
1221
|
+
return this.createTextNode(message.nodeId, message.text, factory);
|
|
1067
1222
|
}
|
|
1068
1223
|
const { tag, nodeId, attributes, children, text } = message;
|
|
1069
1224
|
if (nodeId === void 0 || nodeId === null) {
|
|
@@ -1078,18 +1233,14 @@ var NetworkedDOMWebsocketV01Adapter = class {
|
|
|
1078
1233
|
);
|
|
1079
1234
|
}
|
|
1080
1235
|
if (tag === "#text") {
|
|
1081
|
-
|
|
1082
|
-
textNode.textContent = text || null;
|
|
1083
|
-
this.idToElement.set(nodeId, textNode);
|
|
1084
|
-
this.elementToId.set(textNode, nodeId);
|
|
1085
|
-
return textNode;
|
|
1236
|
+
return this.createTextNode(nodeId, text || "", factory);
|
|
1086
1237
|
}
|
|
1087
1238
|
let element;
|
|
1088
1239
|
try {
|
|
1089
|
-
element = createElementWithSVGSupport(tag, this.options);
|
|
1240
|
+
element = createElementWithSVGSupport(tag, this.options, factory);
|
|
1090
1241
|
} catch (e) {
|
|
1091
1242
|
console.error(`Error creating element: (${tag})`, e);
|
|
1092
|
-
element =
|
|
1243
|
+
element = factory.createElement("x-div");
|
|
1093
1244
|
}
|
|
1094
1245
|
this.idToElement.set(nodeId, element);
|
|
1095
1246
|
this.elementToId.set(element, nodeId);
|
|
@@ -1097,11 +1248,17 @@ var NetworkedDOMWebsocketV01Adapter = class {
|
|
|
1097
1248
|
const value = attributes[key];
|
|
1098
1249
|
setElementAttribute(element, key, value);
|
|
1099
1250
|
}
|
|
1251
|
+
recordFactoryOverride(element, factory, this.docFactory, this.elementFactoryOverride);
|
|
1252
|
+
const { childFactory, usingPortalFactory } = resolvePortalChildFactory(element, factory);
|
|
1100
1253
|
if (children) {
|
|
1101
1254
|
for (const child of children) {
|
|
1102
|
-
const childElement = this.handleNewElement(child);
|
|
1255
|
+
const childElement = this.handleNewElement(child, childFactory);
|
|
1103
1256
|
if (childElement) {
|
|
1104
|
-
|
|
1257
|
+
if (usingPortalFactory) {
|
|
1258
|
+
bufferPortalChild(this.pendingPortalChildren, element, childElement);
|
|
1259
|
+
} else {
|
|
1260
|
+
element.append(childElement);
|
|
1261
|
+
}
|
|
1105
1262
|
}
|
|
1106
1263
|
}
|
|
1107
1264
|
}
|
|
@@ -1110,21 +1267,13 @@ var NetworkedDOMWebsocketV01Adapter = class {
|
|
|
1110
1267
|
};
|
|
1111
1268
|
var connectionId = 1;
|
|
1112
1269
|
var hiddenTag = "x-hidden";
|
|
1113
|
-
var NetworkedDOMWebsocketV02Adapter = class {
|
|
1114
|
-
constructor(websocket, parentElement, connectedCallback, timeCallback, options = {}) {
|
|
1115
|
-
|
|
1116
|
-
this.parentElement = parentElement;
|
|
1117
|
-
this.connectedCallback = connectedCallback;
|
|
1118
|
-
this.timeCallback = timeCallback;
|
|
1119
|
-
this.options = options;
|
|
1120
|
-
this.idToElement = /* @__PURE__ */ new Map();
|
|
1121
|
-
this.elementToId = /* @__PURE__ */ new Map();
|
|
1270
|
+
var NetworkedDOMWebsocketV02Adapter = class extends NetworkedDOMWebsocketAdapterBase {
|
|
1271
|
+
constructor(websocket, parentElement, connectedCallback, timeCallback, options = {}, doc) {
|
|
1272
|
+
super(websocket, parentElement, connectedCallback, timeCallback, options, doc);
|
|
1122
1273
|
this.placeholderToId = /* @__PURE__ */ new Map();
|
|
1123
1274
|
this.hiddenPlaceholderElements = /* @__PURE__ */ new Map();
|
|
1124
|
-
this.currentRoot = null;
|
|
1125
1275
|
this.batchMode = false;
|
|
1126
1276
|
this.batchMessages = [];
|
|
1127
|
-
this.websocket.binaryType = "arraybuffer";
|
|
1128
1277
|
this.protocolSubversion = getNetworkedDOMProtocolSubProtocol_v0_2SubversionOrThrow(
|
|
1129
1278
|
websocket.protocol
|
|
1130
1279
|
);
|
|
@@ -1160,14 +1309,11 @@ var NetworkedDOMWebsocketV02Adapter = class {
|
|
|
1160
1309
|
this.websocket.send(writer.getBuffer());
|
|
1161
1310
|
}
|
|
1162
1311
|
clearContents() {
|
|
1163
|
-
this.
|
|
1164
|
-
this.
|
|
1165
|
-
|
|
1166
|
-
|
|
1167
|
-
|
|
1168
|
-
return true;
|
|
1169
|
-
}
|
|
1170
|
-
return false;
|
|
1312
|
+
this.placeholderToId.clear();
|
|
1313
|
+
this.hiddenPlaceholderElements.clear();
|
|
1314
|
+
this.batchMessages = [];
|
|
1315
|
+
this.batchMode = false;
|
|
1316
|
+
return super.clearContents();
|
|
1171
1317
|
}
|
|
1172
1318
|
receiveMessage(event) {
|
|
1173
1319
|
try {
|
|
@@ -1262,13 +1408,14 @@ var NetworkedDOMWebsocketV02Adapter = class {
|
|
|
1262
1408
|
if (!node) {
|
|
1263
1409
|
throw new Error("No node found for changeHiddenFrom message");
|
|
1264
1410
|
}
|
|
1265
|
-
const
|
|
1411
|
+
const element = node;
|
|
1412
|
+
const parent = element.parentElement;
|
|
1266
1413
|
if (!parent) {
|
|
1267
1414
|
throw new Error("Node has no parent");
|
|
1268
1415
|
}
|
|
1269
|
-
const placeholder =
|
|
1270
|
-
parent.replaceChild(placeholder,
|
|
1271
|
-
this.hiddenPlaceholderElements.set(nodeId, { placeholder, element
|
|
1416
|
+
const placeholder = this.docFactory.createElement(hiddenTag);
|
|
1417
|
+
parent.replaceChild(placeholder, element);
|
|
1418
|
+
this.hiddenPlaceholderElements.set(nodeId, { placeholder, element });
|
|
1272
1419
|
this.placeholderToId.set(placeholder, nodeId);
|
|
1273
1420
|
} else if (removeHiddenFrom.length > 0 && removeHiddenFrom.indexOf(connectionId) !== -1) {
|
|
1274
1421
|
if (!hiddenElement) {
|
|
@@ -1290,18 +1437,19 @@ var NetworkedDOMWebsocketV02Adapter = class {
|
|
|
1290
1437
|
console.warn("No nodeId in childrenChanged message");
|
|
1291
1438
|
return;
|
|
1292
1439
|
}
|
|
1293
|
-
let
|
|
1294
|
-
if (!
|
|
1440
|
+
let parentNode = this.idToElement.get(nodeId);
|
|
1441
|
+
if (!parentNode) {
|
|
1295
1442
|
throw new Error("No parent found for childrenChanged message");
|
|
1296
1443
|
}
|
|
1297
1444
|
const hiddenParent = this.hiddenPlaceholderElements.get(nodeId);
|
|
1298
1445
|
if (hiddenParent) {
|
|
1299
|
-
|
|
1446
|
+
parentNode = hiddenParent.element;
|
|
1300
1447
|
}
|
|
1301
|
-
if (!isHTMLElement(
|
|
1448
|
+
if (!isHTMLElement(parentNode, this.parentElement)) {
|
|
1302
1449
|
throw new Error("Parent is not an HTMLElement (that supports children)");
|
|
1303
1450
|
}
|
|
1304
|
-
const
|
|
1451
|
+
const childFactory = resolveChildFactory(parentNode, this.elementFactoryOverride);
|
|
1452
|
+
const targetForChildren = getChildrenTarget(parentNode);
|
|
1305
1453
|
let nextElement = null;
|
|
1306
1454
|
let previousElement = null;
|
|
1307
1455
|
if (previousNodeId) {
|
|
@@ -1313,23 +1461,20 @@ var NetworkedDOMWebsocketV02Adapter = class {
|
|
|
1313
1461
|
}
|
|
1314
1462
|
const elementsToAdd = [];
|
|
1315
1463
|
for (const addedNode of addedNodes) {
|
|
1316
|
-
const childElement = this.handleNewElement(addedNode);
|
|
1464
|
+
const childElement = this.handleNewElement(addedNode, childFactory);
|
|
1317
1465
|
if (childElement) {
|
|
1318
1466
|
elementsToAdd.push(childElement);
|
|
1319
1467
|
}
|
|
1320
1468
|
}
|
|
1321
|
-
|
|
1322
|
-
|
|
1323
|
-
|
|
1324
|
-
|
|
1325
|
-
|
|
1326
|
-
|
|
1327
|
-
|
|
1328
|
-
|
|
1329
|
-
|
|
1330
|
-
} else {
|
|
1331
|
-
targetForChildren.prepend(...elementsToAdd);
|
|
1332
|
-
}
|
|
1469
|
+
this.insertElements(
|
|
1470
|
+
targetForChildren,
|
|
1471
|
+
elementsToAdd,
|
|
1472
|
+
previousElement,
|
|
1473
|
+
nextElement,
|
|
1474
|
+
childFactory ?? this.docFactory
|
|
1475
|
+
);
|
|
1476
|
+
if (this.pendingPortalChildren.size > 0) {
|
|
1477
|
+
flushPendingPortalChildren(this.pendingPortalChildren);
|
|
1333
1478
|
}
|
|
1334
1479
|
}
|
|
1335
1480
|
handleChildrenRemoved(message) {
|
|
@@ -1338,11 +1483,11 @@ var NetworkedDOMWebsocketV02Adapter = class {
|
|
|
1338
1483
|
console.warn("No nodeId in childrenChanged message");
|
|
1339
1484
|
return;
|
|
1340
1485
|
}
|
|
1341
|
-
const
|
|
1342
|
-
if (!
|
|
1486
|
+
const parentNode = this.idToElement.get(nodeId);
|
|
1487
|
+
if (!parentNode) {
|
|
1343
1488
|
throw new Error("No parent found for childrenChanged message");
|
|
1344
1489
|
}
|
|
1345
|
-
if (!isHTMLElement(
|
|
1490
|
+
if (!isHTMLElement(parentNode, this.parentElement)) {
|
|
1346
1491
|
throw new Error("Parent is not an HTMLElement (that supports children)");
|
|
1347
1492
|
}
|
|
1348
1493
|
for (const removedNode of removedNodes) {
|
|
@@ -1352,7 +1497,7 @@ var NetworkedDOMWebsocketV02Adapter = class {
|
|
|
1352
1497
|
}
|
|
1353
1498
|
this.elementToId.delete(childElement);
|
|
1354
1499
|
this.idToElement.delete(removedNode);
|
|
1355
|
-
const targetForRemoval = getRemovalTarget(
|
|
1500
|
+
const targetForRemoval = getRemovalTarget(parentNode);
|
|
1356
1501
|
const hiddenElement = this.hiddenPlaceholderElements.get(removedNode);
|
|
1357
1502
|
if (hiddenElement) {
|
|
1358
1503
|
const placeholder = hiddenElement.placeholder;
|
|
@@ -1378,62 +1523,36 @@ var NetworkedDOMWebsocketV02Adapter = class {
|
|
|
1378
1523
|
}
|
|
1379
1524
|
}
|
|
1380
1525
|
}
|
|
1381
|
-
|
|
1382
|
-
const
|
|
1383
|
-
if (
|
|
1384
|
-
this.
|
|
1385
|
-
|
|
1386
|
-
|
|
1387
|
-
for (let i = 0; i < childNodes.length; i++) {
|
|
1388
|
-
const child = childNodes[i];
|
|
1389
|
-
const childId = this.elementToId.get(child);
|
|
1390
|
-
if (!childId) {
|
|
1391
|
-
const placeholderId = this.placeholderToId.get(child);
|
|
1392
|
-
if (placeholderId) {
|
|
1393
|
-
const childElement = this.idToElement.get(placeholderId);
|
|
1394
|
-
if (childElement) {
|
|
1395
|
-
this.elementToId.delete(childElement);
|
|
1396
|
-
} else {
|
|
1397
|
-
console.error(
|
|
1398
|
-
"Inner child of removed placeholder element not found by id",
|
|
1399
|
-
placeholderId
|
|
1400
|
-
);
|
|
1401
|
-
}
|
|
1402
|
-
this.idToElement.delete(placeholderId);
|
|
1403
|
-
this.placeholderToId.delete(child);
|
|
1404
|
-
this.hiddenPlaceholderElements.delete(placeholderId);
|
|
1405
|
-
this.removeChildElementIds(childElement);
|
|
1406
|
-
} else {
|
|
1407
|
-
console.error(
|
|
1408
|
-
"Inner child of removed element had no id",
|
|
1409
|
-
child.outerHTML
|
|
1410
|
-
);
|
|
1411
|
-
}
|
|
1526
|
+
handleUnregisteredChild(child) {
|
|
1527
|
+
const placeholderId = this.placeholderToId.get(child);
|
|
1528
|
+
if (placeholderId) {
|
|
1529
|
+
const childElement = this.idToElement.get(placeholderId);
|
|
1530
|
+
if (childElement) {
|
|
1531
|
+
this.elementToId.delete(childElement);
|
|
1412
1532
|
} else {
|
|
1413
|
-
|
|
1414
|
-
|
|
1415
|
-
|
|
1533
|
+
console.error("Inner child of removed placeholder element not found by id", placeholderId);
|
|
1534
|
+
}
|
|
1535
|
+
this.idToElement.delete(placeholderId);
|
|
1536
|
+
this.placeholderToId.delete(child);
|
|
1537
|
+
this.hiddenPlaceholderElements.delete(placeholderId);
|
|
1538
|
+
if (childElement) {
|
|
1539
|
+
this.removeChildElementIds(childElement);
|
|
1416
1540
|
}
|
|
1541
|
+
} else {
|
|
1542
|
+
console.error(
|
|
1543
|
+
"Inner child of removed element had no id",
|
|
1544
|
+
(child == null ? void 0 : child.outerHTML) ?? child
|
|
1545
|
+
);
|
|
1417
1546
|
}
|
|
1418
1547
|
}
|
|
1419
1548
|
handleSnapshot(message) {
|
|
1420
1549
|
var _a;
|
|
1421
|
-
if (this.currentRoot) {
|
|
1422
|
-
this.currentRoot.remove();
|
|
1423
|
-
this.currentRoot = null;
|
|
1424
|
-
this.elementToId.clear();
|
|
1425
|
-
this.idToElement.clear();
|
|
1426
|
-
}
|
|
1427
1550
|
(_a = this.timeCallback) == null ? void 0 : _a.call(this, message.documentTime);
|
|
1428
1551
|
const element = this.handleNewElement(message.snapshot);
|
|
1429
1552
|
if (!element) {
|
|
1430
1553
|
throw new Error("Snapshot element not created");
|
|
1431
1554
|
}
|
|
1432
|
-
|
|
1433
|
-
throw new Error("Snapshot element is not an HTMLElement");
|
|
1434
|
-
}
|
|
1435
|
-
this.currentRoot = element;
|
|
1436
|
-
this.parentElement.append(element);
|
|
1555
|
+
this.resetAndApplySnapshot(element);
|
|
1437
1556
|
}
|
|
1438
1557
|
handleDocumentTime(message) {
|
|
1439
1558
|
var _a;
|
|
@@ -1445,35 +1564,31 @@ var NetworkedDOMWebsocketV02Adapter = class {
|
|
|
1445
1564
|
console.warn("No nodeId in attributeChange message");
|
|
1446
1565
|
return;
|
|
1447
1566
|
}
|
|
1448
|
-
let
|
|
1567
|
+
let node = this.idToElement.get(nodeId);
|
|
1449
1568
|
const hiddenElement = this.hiddenPlaceholderElements.get(nodeId);
|
|
1450
1569
|
if (hiddenElement) {
|
|
1451
|
-
|
|
1570
|
+
node = hiddenElement.element;
|
|
1452
1571
|
}
|
|
1453
|
-
if (
|
|
1454
|
-
if (isHTMLElement(
|
|
1572
|
+
if (node) {
|
|
1573
|
+
if (isHTMLElement(node, this.parentElement)) {
|
|
1455
1574
|
for (const [key, newValue] of attributes) {
|
|
1456
1575
|
if (newValue === null) {
|
|
1457
|
-
|
|
1576
|
+
node.removeAttribute(key);
|
|
1458
1577
|
} else {
|
|
1459
|
-
setElementAttribute(
|
|
1578
|
+
setElementAttribute(node, key, newValue);
|
|
1460
1579
|
}
|
|
1461
1580
|
}
|
|
1462
1581
|
} else {
|
|
1463
|
-
console.error("Element is not an HTMLElement and cannot support attributes",
|
|
1582
|
+
console.error("Element is not an HTMLElement and cannot support attributes", node);
|
|
1464
1583
|
}
|
|
1465
1584
|
} else {
|
|
1466
1585
|
console.error("No element found for attributeChange message");
|
|
1467
1586
|
}
|
|
1468
1587
|
}
|
|
1469
|
-
handleNewElement(message) {
|
|
1588
|
+
handleNewElement(message, factoryOverride) {
|
|
1589
|
+
const factory = factoryOverride ?? this.docFactory;
|
|
1470
1590
|
if (message.type === "text") {
|
|
1471
|
-
|
|
1472
|
-
const textNode = document.createTextNode("");
|
|
1473
|
-
textNode.textContent = text2;
|
|
1474
|
-
this.idToElement.set(nodeId2, textNode);
|
|
1475
|
-
this.elementToId.set(textNode, nodeId2);
|
|
1476
|
-
return textNode;
|
|
1591
|
+
return this.createTextNode(message.nodeId, message.text, factory);
|
|
1477
1592
|
}
|
|
1478
1593
|
const { tag, nodeId, attributes, children, text, hiddenFrom } = message;
|
|
1479
1594
|
if (this.idToElement.has(nodeId)) {
|
|
@@ -1485,34 +1600,36 @@ var NetworkedDOMWebsocketV02Adapter = class {
|
|
|
1485
1600
|
throw new Error("Received nodeId to add that is already present: " + nodeId);
|
|
1486
1601
|
}
|
|
1487
1602
|
if (tag === "#text") {
|
|
1488
|
-
|
|
1489
|
-
textNode.textContent = text || null;
|
|
1490
|
-
this.idToElement.set(nodeId, textNode);
|
|
1491
|
-
this.elementToId.set(textNode, nodeId);
|
|
1492
|
-
return textNode;
|
|
1603
|
+
return this.createTextNode(nodeId, text || "", factory);
|
|
1493
1604
|
}
|
|
1494
1605
|
let element;
|
|
1495
1606
|
try {
|
|
1496
|
-
element = createElementWithSVGSupport(tag, this.options);
|
|
1607
|
+
element = createElementWithSVGSupport(tag, this.options, factory);
|
|
1497
1608
|
} catch (e) {
|
|
1498
1609
|
console.error(`Error creating element: (${tag})`, e);
|
|
1499
|
-
element =
|
|
1610
|
+
element = factory.createElement("x-div");
|
|
1500
1611
|
}
|
|
1501
1612
|
for (const [key, value] of attributes) {
|
|
1502
1613
|
if (value !== null) {
|
|
1503
1614
|
setElementAttribute(element, key, value);
|
|
1504
1615
|
}
|
|
1505
1616
|
}
|
|
1617
|
+
recordFactoryOverride(element, factory, this.docFactory, this.elementFactoryOverride);
|
|
1618
|
+
const { childFactory, usingPortalFactory } = resolvePortalChildFactory(element, factory);
|
|
1506
1619
|
if (children) {
|
|
1507
1620
|
for (const child of children) {
|
|
1508
|
-
const childElement = this.handleNewElement(child);
|
|
1621
|
+
const childElement = this.handleNewElement(child, childFactory);
|
|
1509
1622
|
if (childElement) {
|
|
1510
|
-
|
|
1623
|
+
if (usingPortalFactory) {
|
|
1624
|
+
bufferPortalChild(this.pendingPortalChildren, element, childElement);
|
|
1625
|
+
} else {
|
|
1626
|
+
element.append(childElement);
|
|
1627
|
+
}
|
|
1511
1628
|
}
|
|
1512
1629
|
}
|
|
1513
1630
|
}
|
|
1514
1631
|
if (hiddenFrom && hiddenFrom.length > 0 && hiddenFrom.indexOf(connectionId) !== -1) {
|
|
1515
|
-
const placeholder =
|
|
1632
|
+
const placeholder = this.docFactory.createElement(hiddenTag);
|
|
1516
1633
|
this.hiddenPlaceholderElements.set(nodeId, { placeholder, element });
|
|
1517
1634
|
this.placeholderToId.set(placeholder, nodeId);
|
|
1518
1635
|
this.idToElement.set(nodeId, element);
|
|
@@ -1537,13 +1654,14 @@ var startingBackoffTimeMilliseconds = 100;
|
|
|
1537
1654
|
var maximumBackoffTimeMilliseconds = 1e4;
|
|
1538
1655
|
var maximumWebsocketConnectionTimeout = 3e4;
|
|
1539
1656
|
var NetworkedDOMWebsocket = class {
|
|
1540
|
-
constructor(url, websocketFactory, parentElement, timeCallback, statusUpdateCallback, options = {}) {
|
|
1657
|
+
constructor(url, websocketFactory, parentElement, timeCallback, statusUpdateCallback, options = {}, doc) {
|
|
1541
1658
|
this.url = url;
|
|
1542
1659
|
this.websocketFactory = websocketFactory;
|
|
1543
1660
|
this.parentElement = parentElement;
|
|
1544
1661
|
this.timeCallback = timeCallback;
|
|
1545
1662
|
this.statusUpdateCallback = statusUpdateCallback;
|
|
1546
1663
|
this.options = options;
|
|
1664
|
+
this.doc = doc;
|
|
1547
1665
|
this.websocket = null;
|
|
1548
1666
|
this.websocketAdapter = null;
|
|
1549
1667
|
this.stopped = false;
|
|
@@ -1594,7 +1712,8 @@ var NetworkedDOMWebsocket = class {
|
|
|
1594
1712
|
);
|
|
1595
1713
|
},
|
|
1596
1714
|
this.timeCallback,
|
|
1597
|
-
this.options
|
|
1715
|
+
this.options,
|
|
1716
|
+
this.doc
|
|
1598
1717
|
);
|
|
1599
1718
|
} else {
|
|
1600
1719
|
websocketAdapter = new NetworkedDOMWebsocketV01Adapter(
|
|
@@ -1608,7 +1727,8 @@ var NetworkedDOMWebsocket = class {
|
|
|
1608
1727
|
);
|
|
1609
1728
|
},
|
|
1610
1729
|
this.timeCallback,
|
|
1611
|
-
this.options
|
|
1730
|
+
this.options,
|
|
1731
|
+
this.doc
|
|
1612
1732
|
);
|
|
1613
1733
|
}
|
|
1614
1734
|
this.websocketAdapter = websocketAdapter;
|
|
@@ -1712,22 +1832,35 @@ var NetworkedDOMWebsocket = class {
|
|
|
1712
1832
|
}
|
|
1713
1833
|
};
|
|
1714
1834
|
function isHTMLElement(node, rootNode) {
|
|
1715
|
-
if (node
|
|
1716
|
-
|
|
1717
|
-
|
|
1718
|
-
if (
|
|
1719
|
-
|
|
1720
|
-
|
|
1721
|
-
|
|
1835
|
+
if (!node || typeof node !== "object") return false;
|
|
1836
|
+
const nodeLike = node;
|
|
1837
|
+
if (nodeLike[VIRTUAL_ELEMENT_BRAND] === true) return true;
|
|
1838
|
+
if (typeof HTMLElement !== "undefined" && node instanceof HTMLElement) return true;
|
|
1839
|
+
if (typeof Element !== "undefined" && node instanceof Element) return true;
|
|
1840
|
+
const rootNodeRecord = rootNode;
|
|
1841
|
+
if (rootNodeRecord == null ? void 0 : rootNodeRecord.ownerDocument) {
|
|
1842
|
+
const ownerDoc = rootNodeRecord.ownerDocument;
|
|
1843
|
+
const defaultView = ownerDoc.defaultView;
|
|
1844
|
+
if (defaultView == null ? void 0 : defaultView.HTMLElement) {
|
|
1845
|
+
return node instanceof defaultView.HTMLElement;
|
|
1846
|
+
}
|
|
1847
|
+
}
|
|
1848
|
+
return false;
|
|
1722
1849
|
}
|
|
1723
1850
|
function isText(node, rootNode) {
|
|
1724
|
-
if (node
|
|
1725
|
-
|
|
1726
|
-
|
|
1727
|
-
if (
|
|
1728
|
-
|
|
1729
|
-
|
|
1730
|
-
|
|
1851
|
+
if (!node || typeof node !== "object") return false;
|
|
1852
|
+
const nodeLike = node;
|
|
1853
|
+
if (nodeLike[VIRTUAL_TEXT_BRAND] === true) return true;
|
|
1854
|
+
if (typeof Text !== "undefined" && node instanceof Text) return true;
|
|
1855
|
+
const rootNodeRecord = rootNode;
|
|
1856
|
+
if (rootNodeRecord == null ? void 0 : rootNodeRecord.ownerDocument) {
|
|
1857
|
+
const ownerDoc = rootNodeRecord.ownerDocument;
|
|
1858
|
+
const defaultView = ownerDoc.defaultView;
|
|
1859
|
+
if (defaultView == null ? void 0 : defaultView.Text) {
|
|
1860
|
+
return node instanceof defaultView.Text;
|
|
1861
|
+
}
|
|
1862
|
+
}
|
|
1863
|
+
return false;
|
|
1731
1864
|
}
|
|
1732
1865
|
|
|
1733
1866
|
// src/index.ts
|