@xmldom/xmldom 0.9.0-beta.5 → 0.9.0-beta.6
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/CHANGELOG.md +12 -3
- package/lib/dom.js +173 -26
- package/package.json +2 -2
package/CHANGELOG.md
CHANGED
|
@@ -4,9 +4,18 @@ All notable changes to this project will be documented in this file.
|
|
|
4
4
|
|
|
5
5
|
This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
6
6
|
|
|
7
|
+
## [0.9.0-beta.6](https://github.com/xmldom/xmldom/compare/0.9.0-beta.5...0.9.0-beta.)
|
|
8
|
+
|
|
9
|
+
### Fixed
|
|
10
|
+
|
|
11
|
+
- Properly check nodes before replacement [`#457`](https://github.com/xmldom/xmldom/pull/457) / [`#455`](https://github.com/xmldom/xmldom/issues/455)
|
|
12
|
+
|
|
13
|
+
Thank you, [@edemaine](https://github.com/edemaine), [@pedro-l9](https://github.com/pedro-l9), for your contributions
|
|
14
|
+
|
|
15
|
+
|
|
7
16
|
## [0.9.0-beta.5](https://github.com/xmldom/xmldom/compare/0.9.0-beta.4...0.9.0-beta.5)
|
|
8
17
|
|
|
9
|
-
###
|
|
18
|
+
### Fixed
|
|
10
19
|
|
|
11
20
|
- fix: Restore ES5 compatibility [`#452`](https://github.com/xmldom/xmldom/pull/452) / [`#453`](https://github.com/xmldom/xmldom/issues/453)
|
|
12
21
|
|
|
@@ -15,7 +24,7 @@ Thank you, [@fengxinming](https://github.com/fengxinming), for your contribution
|
|
|
15
24
|
|
|
16
25
|
## [0.8.5](https://github.com/xmldom/xmldom/compare/0.8.4...0.8.5)
|
|
17
26
|
|
|
18
|
-
###
|
|
27
|
+
### Fixed
|
|
19
28
|
|
|
20
29
|
- fix: Restore ES5 compatibility [`#452`](https://github.com/xmldom/xmldom/pull/452) / [`#453`](https://github.com/xmldom/xmldom/issues/453)
|
|
21
30
|
|
|
@@ -24,7 +33,7 @@ Thank you, [@fengxinming](https://github.com/fengxinming), for your contribution
|
|
|
24
33
|
|
|
25
34
|
## [0.7.8](https://github.com/xmldom/xmldom/compare/0.7.7...0.7.8)
|
|
26
35
|
|
|
27
|
-
###
|
|
36
|
+
### Fixed
|
|
28
37
|
|
|
29
38
|
- fix: Restore ES5 compatibility [`#452`](https://github.com/xmldom/xmldom/pull/452) / [`#453`](https://github.com/xmldom/xmldom/issues/453)
|
|
30
39
|
|
package/lib/dom.js
CHANGED
|
@@ -514,7 +514,7 @@ Node.prototype = {
|
|
|
514
514
|
},
|
|
515
515
|
replaceChild: function (newChild, oldChild) {
|
|
516
516
|
//raises
|
|
517
|
-
this
|
|
517
|
+
_insertBefore(this, newChild, oldChild, assertPreReplacementValidityInDocument);
|
|
518
518
|
if (oldChild) {
|
|
519
519
|
this.removeChild(oldChild);
|
|
520
520
|
}
|
|
@@ -831,8 +831,35 @@ function isElementInsertionPossible(doc, child) {
|
|
|
831
831
|
var docTypeNode = find(parentChildNodes, isDocTypeNode);
|
|
832
832
|
return !(child && docTypeNode && parentChildNodes.indexOf(docTypeNode) > parentChildNodes.indexOf(child));
|
|
833
833
|
}
|
|
834
|
+
|
|
835
|
+
/**
|
|
836
|
+
* Check if en element node can be inserted before `child`, or at the end if child is falsy,
|
|
837
|
+
* according to the presence and position of a doctype node on the same level.
|
|
838
|
+
*
|
|
839
|
+
* @param {Node} doc The document node
|
|
840
|
+
* @param {Node} child the node that would become the nextSibling if the element would be inserted
|
|
841
|
+
* @returns {boolean} `true` if an element can be inserted before child
|
|
842
|
+
* @private
|
|
843
|
+
* https://dom.spec.whatwg.org/#concept-node-ensure-pre-insertion-validity
|
|
844
|
+
*/
|
|
845
|
+
function isElementReplacementPossible(doc, child) {
|
|
846
|
+
var parentChildNodes = doc.childNodes || [];
|
|
847
|
+
|
|
848
|
+
function hasElementChildThatIsNotChild(node) {
|
|
849
|
+
return isElementNode(node) && node !== child;
|
|
850
|
+
}
|
|
851
|
+
|
|
852
|
+
if (find(parentChildNodes, hasElementChildThatIsNotChild)) {
|
|
853
|
+
return false;
|
|
854
|
+
}
|
|
855
|
+
var docTypeNode = find(parentChildNodes, isDocTypeNode);
|
|
856
|
+
return !(child && docTypeNode && parentChildNodes.indexOf(docTypeNode) > parentChildNodes.indexOf(child));
|
|
857
|
+
}
|
|
858
|
+
|
|
834
859
|
/**
|
|
835
860
|
* @private
|
|
861
|
+
* Steps 1-5 of the checks before inserting and before replacing a child are the same.
|
|
862
|
+
*
|
|
836
863
|
* @param {Node} parent the parent node to insert `node` into
|
|
837
864
|
* @param {Node} node the node to insert
|
|
838
865
|
* @param {Node=} child the node that should become the `nextSibling` of `node`
|
|
@@ -840,18 +867,26 @@ function isElementInsertionPossible(doc, child) {
|
|
|
840
867
|
* @throws DOMException for several node combinations that would create a DOM that is not well-formed.
|
|
841
868
|
* @throws DOMException if `child` is provided but is not a child of `parent`.
|
|
842
869
|
* @see https://dom.spec.whatwg.org/#concept-node-ensure-pre-insertion-validity
|
|
870
|
+
* @see https://dom.spec.whatwg.org/#concept-node-replace
|
|
843
871
|
*/
|
|
844
|
-
function
|
|
872
|
+
function assertPreInsertionValidity1to5(parent, node, child) {
|
|
873
|
+
// 1. If `parent` is not a Document, DocumentFragment, or Element node, then throw a "HierarchyRequestError" DOMException.
|
|
845
874
|
if (!hasValidParentNodeType(parent)) {
|
|
846
875
|
throw new DOMException(HIERARCHY_REQUEST_ERR, 'Unexpected parent node type ' + parent.nodeType);
|
|
847
876
|
}
|
|
877
|
+
// 2. If `node` is a host-including inclusive ancestor of `parent`, then throw a "HierarchyRequestError" DOMException.
|
|
878
|
+
// not implemented!
|
|
879
|
+
// 3. If `child` is non-null and its parent is not `parent`, then throw a "NotFoundError" DOMException.
|
|
848
880
|
if (child && child.parentNode !== parent) {
|
|
849
881
|
throw new DOMException(NOT_FOUND_ERR, 'child not in parent');
|
|
850
882
|
}
|
|
851
883
|
if (
|
|
884
|
+
// 4. If `node` is not a DocumentFragment, DocumentType, Element, or CharacterData node, then throw a "HierarchyRequestError" DOMException.
|
|
852
885
|
!hasInsertableNodeType(node) ||
|
|
886
|
+
// 5. If either `node` is a Text node and `parent` is a document,
|
|
853
887
|
// the sax parser currently adds top level text nodes, this will be fixed in 0.9.0
|
|
854
888
|
// || (node.nodeType === Node.TEXT_NODE && parent.nodeType === Node.DOCUMENT_NODE)
|
|
889
|
+
// or `node` is a doctype and `parent` is not a document, then throw a "HierarchyRequestError" DOMException.
|
|
855
890
|
(isDocTypeNode(node) && parent.nodeType !== Node.DOCUMENT_NODE)
|
|
856
891
|
) {
|
|
857
892
|
throw new DOMException(
|
|
@@ -859,36 +894,137 @@ function _insertBefore(parent, node, child) {
|
|
|
859
894
|
'Unexpected node type ' + node.nodeType + ' for parent node type ' + parent.nodeType
|
|
860
895
|
);
|
|
861
896
|
}
|
|
897
|
+
}
|
|
898
|
+
|
|
899
|
+
/**
|
|
900
|
+
* @private
|
|
901
|
+
* Step 6 of the checks before inserting and before replacing a child are different.
|
|
902
|
+
*
|
|
903
|
+
* @param {Document} parent the parent node to insert `node` into
|
|
904
|
+
* @param {Node} node the node to insert
|
|
905
|
+
* @param {Node | undefined} child the node that should become the `nextSibling` of `node`
|
|
906
|
+
* @returns {Node}
|
|
907
|
+
* @throws DOMException for several node combinations that would create a DOM that is not well-formed.
|
|
908
|
+
* @throws DOMException if `child` is provided but is not a child of `parent`.
|
|
909
|
+
* @see https://dom.spec.whatwg.org/#concept-node-ensure-pre-insertion-validity
|
|
910
|
+
* @see https://dom.spec.whatwg.org/#concept-node-replace
|
|
911
|
+
*/
|
|
912
|
+
function assertPreInsertionValidityInDocument(parent, node, child) {
|
|
862
913
|
var parentChildNodes = parent.childNodes || [];
|
|
863
914
|
var nodeChildNodes = node.childNodes || [];
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
throw new DOMException(HIERARCHY_REQUEST_ERR, 'Element in fragment can not be inserted before doctype');
|
|
872
|
-
}
|
|
915
|
+
|
|
916
|
+
// DocumentFragment
|
|
917
|
+
if (node.nodeType === Node.DOCUMENT_FRAGMENT_NODE) {
|
|
918
|
+
var nodeChildElements = nodeChildNodes.filter(isElementNode);
|
|
919
|
+
// If node has more than one element child or has a Text node child.
|
|
920
|
+
if (nodeChildElements.length > 1 || find(nodeChildNodes, isTextNode)) {
|
|
921
|
+
throw new DOMException(HIERARCHY_REQUEST_ERR, 'More than one element or text in fragment');
|
|
873
922
|
}
|
|
874
|
-
if
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
923
|
+
// Otherwise, if `node` has one element child and either `parent` has an element child,
|
|
924
|
+
// `child` is a doctype, or `child` is non-null and a doctype is following `child`.
|
|
925
|
+
if (nodeChildElements.length === 1 && !isElementInsertionPossible(parent, child)) {
|
|
926
|
+
throw new DOMException(HIERARCHY_REQUEST_ERR, 'Element in fragment can not be inserted before doctype');
|
|
878
927
|
}
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
}
|
|
887
|
-
if (!child && parentElementChild) {
|
|
888
|
-
throw new DOMException(HIERARCHY_REQUEST_ERR, 'Doctype can not be appended since element is present');
|
|
889
|
-
}
|
|
928
|
+
}
|
|
929
|
+
// Element
|
|
930
|
+
if (isElementNode(node)) {
|
|
931
|
+
// `parent` has an element child, `child` is a doctype,
|
|
932
|
+
// or `child` is non-null and a doctype is following `child`.
|
|
933
|
+
if (!isElementInsertionPossible(parent, child)) {
|
|
934
|
+
throw new DOMException(HIERARCHY_REQUEST_ERR, 'Only one element can be added and only after doctype');
|
|
890
935
|
}
|
|
891
936
|
}
|
|
937
|
+
// DocumentType
|
|
938
|
+
if (isDocTypeNode(node)) {
|
|
939
|
+
// `parent` has a doctype child,
|
|
940
|
+
if (find(parentChildNodes, isDocTypeNode)) {
|
|
941
|
+
throw new DOMException(HIERARCHY_REQUEST_ERR, 'Only one doctype is allowed');
|
|
942
|
+
}
|
|
943
|
+
var parentElementChild = find(parentChildNodes, isElementNode);
|
|
944
|
+
// `child` is non-null and an element is preceding `child`,
|
|
945
|
+
if (child && parentChildNodes.indexOf(parentElementChild) < parentChildNodes.indexOf(child)) {
|
|
946
|
+
throw new DOMException(HIERARCHY_REQUEST_ERR, 'Doctype can only be inserted before an element');
|
|
947
|
+
}
|
|
948
|
+
// or `child` is null and `parent` has an element child.
|
|
949
|
+
if (!child && parentElementChild) {
|
|
950
|
+
throw new DOMException(HIERARCHY_REQUEST_ERR, 'Doctype can not be appended since element is present');
|
|
951
|
+
}
|
|
952
|
+
}
|
|
953
|
+
}
|
|
954
|
+
|
|
955
|
+
/**
|
|
956
|
+
* @private
|
|
957
|
+
* Step 6 of the checks before inserting and before replacing a child are different.
|
|
958
|
+
*
|
|
959
|
+
* @param {Document} parent the parent node to insert `node` into
|
|
960
|
+
* @param {Node} node the node to insert
|
|
961
|
+
* @param {Node | undefined} child the node that should become the `nextSibling` of `node`
|
|
962
|
+
* @returns {Node}
|
|
963
|
+
* @throws DOMException for several node combinations that would create a DOM that is not well-formed.
|
|
964
|
+
* @throws DOMException if `child` is provided but is not a child of `parent`.
|
|
965
|
+
* @see https://dom.spec.whatwg.org/#concept-node-ensure-pre-insertion-validity
|
|
966
|
+
* @see https://dom.spec.whatwg.org/#concept-node-replace
|
|
967
|
+
*/
|
|
968
|
+
function assertPreReplacementValidityInDocument(parent, node, child) {
|
|
969
|
+
var parentChildNodes = parent.childNodes || [];
|
|
970
|
+
var nodeChildNodes = node.childNodes || [];
|
|
971
|
+
|
|
972
|
+
// DocumentFragment
|
|
973
|
+
if (node.nodeType === Node.DOCUMENT_FRAGMENT_NODE) {
|
|
974
|
+
var nodeChildElements = nodeChildNodes.filter(isElementNode);
|
|
975
|
+
// If `node` has more than one element child or has a Text node child.
|
|
976
|
+
if (nodeChildElements.length > 1 || find(nodeChildNodes, isTextNode)) {
|
|
977
|
+
throw new DOMException(HIERARCHY_REQUEST_ERR, 'More than one element or text in fragment');
|
|
978
|
+
}
|
|
979
|
+
// Otherwise, if `node` has one element child and either `parent` has an element child that is not `child` or a doctype is following `child`.
|
|
980
|
+
if (nodeChildElements.length === 1 && !isElementReplacementPossible(parent, child)) {
|
|
981
|
+
throw new DOMException(HIERARCHY_REQUEST_ERR, 'Element in fragment can not be inserted before doctype');
|
|
982
|
+
}
|
|
983
|
+
}
|
|
984
|
+
// Element
|
|
985
|
+
if (isElementNode(node)) {
|
|
986
|
+
// `parent` has an element child that is not `child` or a doctype is following `child`.
|
|
987
|
+
if (!isElementReplacementPossible(parent, child)) {
|
|
988
|
+
throw new DOMException(HIERARCHY_REQUEST_ERR, 'Only one element can be added and only after doctype');
|
|
989
|
+
}
|
|
990
|
+
}
|
|
991
|
+
// DocumentType
|
|
992
|
+
if (isDocTypeNode(node)) {
|
|
993
|
+
function hasDoctypeChildThatIsNotChild(node) {
|
|
994
|
+
return isDocTypeNode(node) && node !== child;
|
|
995
|
+
}
|
|
996
|
+
|
|
997
|
+
// `parent` has a doctype child that is not `child`,
|
|
998
|
+
if (find(parentChildNodes, hasDoctypeChildThatIsNotChild)) {
|
|
999
|
+
throw new DOMException(HIERARCHY_REQUEST_ERR, 'Only one doctype is allowed');
|
|
1000
|
+
}
|
|
1001
|
+
var parentElementChild = find(parentChildNodes, isElementNode);
|
|
1002
|
+
// or an element is preceding `child`.
|
|
1003
|
+
if (child && parentChildNodes.indexOf(parentElementChild) < parentChildNodes.indexOf(child)) {
|
|
1004
|
+
throw new DOMException(HIERARCHY_REQUEST_ERR, 'Doctype can only be inserted before an element');
|
|
1005
|
+
}
|
|
1006
|
+
}
|
|
1007
|
+
}
|
|
1008
|
+
|
|
1009
|
+
/**
|
|
1010
|
+
* @private
|
|
1011
|
+
* @param {Node} parent the parent node to insert `node` into
|
|
1012
|
+
* @param {Node} node the node to insert
|
|
1013
|
+
* @param {Node=} child the node that should become the `nextSibling` of `node`
|
|
1014
|
+
* @returns {Node}
|
|
1015
|
+
* @throws DOMException for several node combinations that would create a DOM that is not well-formed.
|
|
1016
|
+
* @throws DOMException if `child` is provided but is not a child of `parent`.
|
|
1017
|
+
* @see https://dom.spec.whatwg.org/#concept-node-ensure-pre-insertion-validity
|
|
1018
|
+
*/
|
|
1019
|
+
function _insertBefore(parent, node, child, _inDocumentAssertion) {
|
|
1020
|
+
// To ensure pre-insertion validity of a node into a parent before a child, run these steps:
|
|
1021
|
+
assertPreInsertionValidity1to5(parent, node, child);
|
|
1022
|
+
|
|
1023
|
+
// If parent is a document, and any of the statements below, switched on the interface node implements,
|
|
1024
|
+
// are true, then throw a "HierarchyRequestError" DOMException.
|
|
1025
|
+
if (parent.nodeType === Node.DOCUMENT_NODE) {
|
|
1026
|
+
(_inDocumentAssertion || assertPreInsertionValidityInDocument)(parent, node, child);
|
|
1027
|
+
}
|
|
892
1028
|
|
|
893
1029
|
var cp = node.parentNode;
|
|
894
1030
|
if (cp) {
|
|
@@ -1001,6 +1137,17 @@ Document.prototype = {
|
|
|
1001
1137
|
}
|
|
1002
1138
|
return _removeChild(this, oldChild);
|
|
1003
1139
|
},
|
|
1140
|
+
replaceChild: function (newChild, oldChild) {
|
|
1141
|
+
//raises
|
|
1142
|
+
_insertBefore(this, newChild, oldChild, assertPreReplacementValidityInDocument);
|
|
1143
|
+
newChild.ownerDocument = this;
|
|
1144
|
+
if (oldChild) {
|
|
1145
|
+
this.removeChild(oldChild);
|
|
1146
|
+
}
|
|
1147
|
+
if (isElementNode(newChild)) {
|
|
1148
|
+
this.documentElement = newChild;
|
|
1149
|
+
}
|
|
1150
|
+
},
|
|
1004
1151
|
// Introduced in DOM Level 2:
|
|
1005
1152
|
importNode: function (importedNode, deep) {
|
|
1006
1153
|
return importNode(this, importedNode, deep);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@xmldom/xmldom",
|
|
3
|
-
"version": "0.9.0-beta.
|
|
3
|
+
"version": "0.9.0-beta.6",
|
|
4
4
|
"description": "A pure JavaScript W3C standard-based (XML DOM Level 2 Core) DOMParser and XMLSerializer module.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"w3c",
|
|
@@ -35,7 +35,7 @@
|
|
|
35
35
|
"stryker": "stryker run",
|
|
36
36
|
"stryker:dry-run": "stryker run -m '' --reporters progress",
|
|
37
37
|
"test": "jest",
|
|
38
|
-
"testrelease": "npm test &&
|
|
38
|
+
"testrelease": "npm test && eslint lib",
|
|
39
39
|
"version": "./changelog-has-version.sh",
|
|
40
40
|
"release": "np --no-yarn --test-script testrelease"
|
|
41
41
|
},
|