@angular/platform-server 21.2.21 → 21.2.23
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/fesm2022/_server-chunk.mjs +17 -18
- package/fesm2022/_server-chunk.mjs.map +1 -1
- package/fesm2022/init.mjs +1 -1
- package/fesm2022/platform-server.mjs +2 -2
- package/fesm2022/platform-server.mjs.map +1 -1
- package/fesm2022/testing.mjs +5 -5
- package/fesm2022/testing.mjs.map +1 -1
- package/package.json +5 -5
- package/third_party/domino/bundled-domino.mjs +99 -21
- package/third_party/domino/bundled-domino.mjs.map +1 -1
- package/types/init.d.ts +1 -1
- package/types/platform-server.d.ts +1 -1
- package/types/testing.d.ts +1 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@angular/platform-server",
|
|
3
|
-
"version": "21.2.
|
|
3
|
+
"version": "21.2.23",
|
|
4
4
|
"description": "Angular - library for using Angular in Node.js",
|
|
5
5
|
"author": "angular",
|
|
6
6
|
"license": "MIT",
|
|
@@ -8,10 +8,10 @@
|
|
|
8
8
|
"node": "^20.19.0 || ^22.12.0 || >=24.0.0"
|
|
9
9
|
},
|
|
10
10
|
"peerDependencies": {
|
|
11
|
-
"@angular/common": "21.2.
|
|
12
|
-
"@angular/compiler": "21.2.
|
|
13
|
-
"@angular/core": "21.2.
|
|
14
|
-
"@angular/platform-browser": "21.2.
|
|
11
|
+
"@angular/common": "21.2.23",
|
|
12
|
+
"@angular/compiler": "21.2.23",
|
|
13
|
+
"@angular/core": "21.2.23",
|
|
14
|
+
"@angular/platform-browser": "21.2.23",
|
|
15
15
|
"rxjs": "^6.5.3 || ^7.4.0"
|
|
16
16
|
},
|
|
17
17
|
"dependencies": {
|
|
@@ -848,6 +848,23 @@ function requireNodeUtils () {
|
|
|
848
848
|
return a.name;
|
|
849
849
|
}
|
|
850
850
|
|
|
851
|
+
function fallbackRawContentTags(node) {
|
|
852
|
+
const tags = [];
|
|
853
|
+
while (node) {
|
|
854
|
+
if (node.nodeType === 1 /*ELEMENT_NODE*/) {
|
|
855
|
+
if (node.namespaceURI === NAMESPACE.HTML && hasRawContentFallback[node.tagName]) {
|
|
856
|
+
tags.push(node.localName);
|
|
857
|
+
}
|
|
858
|
+
node = node.parentNode;
|
|
859
|
+
} else if (node.nodeType === 11 /*DOCUMENT_FRAGMENT_NODE*/ && node._host) {
|
|
860
|
+
node = node._host;
|
|
861
|
+
} else {
|
|
862
|
+
node = node.parentNode;
|
|
863
|
+
}
|
|
864
|
+
}
|
|
865
|
+
return tags;
|
|
866
|
+
}
|
|
867
|
+
|
|
851
868
|
/**
|
|
852
869
|
* Escapes matching closing tag in a raw text.
|
|
853
870
|
*
|
|
@@ -877,12 +894,22 @@ function requireNodeUtils () {
|
|
|
877
894
|
return text.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
878
895
|
}
|
|
879
896
|
|
|
880
|
-
function
|
|
881
|
-
|
|
882
|
-
|
|
897
|
+
function escapeMatchingClosingTags(rawText, parentTag, ancestorTags) {
|
|
898
|
+
let result = escapeMatchingClosingTag(rawText, parentTag);
|
|
899
|
+
if (ancestorTags) {
|
|
900
|
+
for (const ancestorTag of ancestorTags) {
|
|
901
|
+
result = escapeMatchingClosingTag(result, ancestorTag);
|
|
902
|
+
}
|
|
903
|
+
}
|
|
904
|
+
return result;
|
|
905
|
+
}
|
|
906
|
+
|
|
907
|
+
function escapeFallbackRawText(rawText, parentTag, ancestorTags) {
|
|
908
|
+
let result = '';
|
|
909
|
+
let index = 0;
|
|
883
910
|
|
|
884
911
|
while (index < rawText.length) {
|
|
885
|
-
|
|
912
|
+
const commentStart = rawText.indexOf('<!--', index);
|
|
886
913
|
if (commentStart === -1) {
|
|
887
914
|
result += escape(rawText.slice(index));
|
|
888
915
|
break;
|
|
@@ -890,15 +917,15 @@ function requireNodeUtils () {
|
|
|
890
917
|
|
|
891
918
|
result += escape(rawText.slice(index, commentStart));
|
|
892
919
|
|
|
893
|
-
|
|
920
|
+
const commentEnd = findCommentEnd(rawText, commentStart + 4);
|
|
894
921
|
if (commentEnd === -1) {
|
|
895
|
-
result +=
|
|
922
|
+
result += escapeMatchingClosingTags(rawText.slice(commentStart), parentTag, ancestorTags);
|
|
896
923
|
break;
|
|
897
924
|
}
|
|
898
925
|
|
|
899
926
|
// A complete HTML comment remains inert if downstream tooling reparses
|
|
900
927
|
// fallback raw text as normal HTML, so preserve its comment semantics.
|
|
901
|
-
result +=
|
|
928
|
+
result += escapeMatchingClosingTags(rawText.slice(commentStart, commentEnd), parentTag, ancestorTags);
|
|
902
929
|
index = commentEnd;
|
|
903
930
|
}
|
|
904
931
|
|
|
@@ -911,24 +938,47 @@ function requireNodeUtils () {
|
|
|
911
938
|
if (rawText.charAt(index) === '-' && rawText.charAt(index + 1) === '>')
|
|
912
939
|
return index + 2;
|
|
913
940
|
|
|
914
|
-
|
|
941
|
+
const match = CLOSING_COMMENT_REGEXP.exec(rawText.slice(index));
|
|
915
942
|
return match ? index + match.index + match[0].length : -1;
|
|
916
943
|
}
|
|
917
944
|
|
|
918
945
|
const CLOSING_COMMENT_REGEXP = /--!?>/;
|
|
919
946
|
|
|
947
|
+
/**
|
|
948
|
+
* Escapes a comment content that abruptly closes the comment.
|
|
949
|
+
*
|
|
950
|
+
* A comment can not carry content that starts with `>` or `->`: the parser
|
|
951
|
+
* closes the comment as soon as it comes across such a sequence right after
|
|
952
|
+
* `<!--` (the "abrupt-closing-of-empty-comment" parse error). For example,
|
|
953
|
+
* `#comment('><img src=x onerror=alert(1)>')` would otherwise serialize into
|
|
954
|
+
* `<!--><img src=x onerror=alert(1)>-->`, which de-serializes into an empty
|
|
955
|
+
* comment followed by a live `<img>` element. Escaping the leading `>` keeps
|
|
956
|
+
* the content inside the comment, where it stays inert.
|
|
957
|
+
*/
|
|
958
|
+
function escapeAbruptClosingCommentTag(rawContent) {
|
|
959
|
+
if (rawContent.startsWith('>')) {
|
|
960
|
+
return '>' + rawContent.slice(1);
|
|
961
|
+
}
|
|
962
|
+
if (rawContent.startsWith('->')) {
|
|
963
|
+
return '->' + rawContent.slice(2);
|
|
964
|
+
}
|
|
965
|
+
return rawContent; // fast path
|
|
966
|
+
}
|
|
967
|
+
|
|
920
968
|
/**
|
|
921
969
|
* Escapes closing comment tag in a comment content.
|
|
922
970
|
*
|
|
923
971
|
* For example, given `#comment('-->')`, the content of a comment would be
|
|
924
972
|
* updated to `-->` to avoid unexpected and unsafe behavior after
|
|
925
|
-
* de-serialization.
|
|
973
|
+
* de-serialization. Content that abruptly closes an empty comment is
|
|
974
|
+
* escaped as well, see `escapeAbruptClosingCommentTag()`.
|
|
926
975
|
*/
|
|
927
976
|
function escapeClosingCommentTag(rawContent) {
|
|
928
|
-
|
|
929
|
-
|
|
977
|
+
const content = escapeAbruptClosingCommentTag(rawContent);
|
|
978
|
+
if (!CLOSING_COMMENT_REGEXP.test(content)) {
|
|
979
|
+
return content; // fast path
|
|
930
980
|
}
|
|
931
|
-
return
|
|
981
|
+
return content.replace(/(--\!?)>/g, '$1>');
|
|
932
982
|
}
|
|
933
983
|
|
|
934
984
|
/**
|
|
@@ -962,8 +1012,12 @@ function requireNodeUtils () {
|
|
|
962
1012
|
// If an element can have raw content, this content may
|
|
963
1013
|
// potentially require escaping to avoid XSS.
|
|
964
1014
|
var upperTag = tagname.toUpperCase();
|
|
965
|
-
if (hasRawContent[upperTag] && !hasRawContentFallback[upperTag]) {
|
|
1015
|
+
if (hasRawContent[upperTag] && !hasRawContentFallback[upperTag] && ss.includes('</')) {
|
|
966
1016
|
ss = escapeMatchingClosingTag(ss, tagname);
|
|
1017
|
+
const fallbackTags = fallbackRawContentTags(parent);
|
|
1018
|
+
for (const fallbackTag of fallbackTags) {
|
|
1019
|
+
ss = escapeMatchingClosingTag(ss, fallbackTag);
|
|
1020
|
+
}
|
|
967
1021
|
}
|
|
968
1022
|
if (html && extraNewLine[tagname] && ss.charAt(0)==='\n') s += '\n';
|
|
969
1023
|
// Serialize children and add end tag for all others
|
|
@@ -983,22 +1037,33 @@ function requireNodeUtils () {
|
|
|
983
1037
|
if (hasRawContent[parenttag]) {
|
|
984
1038
|
// Preserve actual child element markup in fallback elements such as
|
|
985
1039
|
// <noscript>, but do not emit text-node payloads as raw HTML.
|
|
986
|
-
s += hasRawContentFallback[parenttag] ? escapeFallbackRawText(kid.data, parent.localName) : kid.data;
|
|
1040
|
+
s += hasRawContentFallback[parenttag] ? escapeFallbackRawText(kid.data, parent.localName, fallbackRawContentTags(parent.parentNode)) : kid.data;
|
|
987
1041
|
} else {
|
|
988
1042
|
s += escape(kid.data);
|
|
989
1043
|
}
|
|
990
1044
|
break;
|
|
991
1045
|
case 8: //COMMENT_NODE
|
|
992
|
-
|
|
1046
|
+
let commentData = escapeClosingCommentTag(kid.data);
|
|
1047
|
+
if (commentData.includes('</')) {
|
|
1048
|
+
const fallbackTags = fallbackRawContentTags(parent);
|
|
1049
|
+
for (const fallbackTag of fallbackTags) {
|
|
1050
|
+
commentData = escapeMatchingClosingTag(commentData, fallbackTag);
|
|
1051
|
+
}
|
|
1052
|
+
}
|
|
1053
|
+
s += '<!--' + commentData + '-->';
|
|
993
1054
|
break;
|
|
994
1055
|
case 7: //PROCESSING_INSTRUCTION_NODE
|
|
995
|
-
|
|
1056
|
+
let content = escapeProcessingInstructionContent(kid.data);
|
|
1057
|
+
if (content.includes('</')) {
|
|
1058
|
+
const fallbackTags = fallbackRawContentTags(parent);
|
|
1059
|
+
for (const fallbackTag of fallbackTags) {
|
|
1060
|
+
content = escapeMatchingClosingTag(content, fallbackTag);
|
|
1061
|
+
}
|
|
1062
|
+
}
|
|
996
1063
|
s += '<?' + kid.target + ' ' + content + '?>';
|
|
997
1064
|
break;
|
|
998
1065
|
case 10: //DOCUMENT_TYPE_NODE
|
|
999
|
-
s += '<!DOCTYPE ' + kid.name;
|
|
1000
|
-
|
|
1001
|
-
s += '>';
|
|
1066
|
+
s += '<!DOCTYPE ' + kid.name + '>';
|
|
1002
1067
|
break;
|
|
1003
1068
|
default:
|
|
1004
1069
|
utils.InvalidStateError();
|
|
@@ -7588,7 +7653,7 @@ function requireHtmlelts () {
|
|
|
7588
7653
|
required: Boolean,
|
|
7589
7654
|
readOnly: Boolean,
|
|
7590
7655
|
checked: Boolean,
|
|
7591
|
-
value: String,
|
|
7656
|
+
value: { type: String, treatNullAsEmptyString: true },
|
|
7592
7657
|
src: URL,
|
|
7593
7658
|
defaultChecked: {name: 'checked', type: Boolean},
|
|
7594
7659
|
size: {type: 'unsigned long', default: 20, min: 1, setmin: 1},
|
|
@@ -8111,10 +8176,21 @@ function requireHtmlelts () {
|
|
|
8111
8176
|
ctor: function HTMLTemplateElement(doc, localName, prefix) {
|
|
8112
8177
|
HTMLElement.call(this, doc, localName, prefix);
|
|
8113
8178
|
this._contentFragment = doc._templateDoc.createDocumentFragment();
|
|
8179
|
+
this._contentFragment._host = this;
|
|
8114
8180
|
},
|
|
8115
8181
|
props: {
|
|
8116
8182
|
content: { get: function() { return this._contentFragment; } },
|
|
8117
|
-
serialize: { value: function() { return this.content.serialize(); } }
|
|
8183
|
+
serialize: { value: function() { return this.content.serialize(); } },
|
|
8184
|
+
cloneNode: {
|
|
8185
|
+
value: function(deep) {
|
|
8186
|
+
var clone = HTMLElement.prototype.cloneNode.call(this, deep);
|
|
8187
|
+
if (deep) {
|
|
8188
|
+
clone._contentFragment = this._contentFragment.cloneNode(true);
|
|
8189
|
+
clone._contentFragment._host = clone;
|
|
8190
|
+
}
|
|
8191
|
+
return clone;
|
|
8192
|
+
}
|
|
8193
|
+
}
|
|
8118
8194
|
}
|
|
8119
8195
|
});
|
|
8120
8196
|
|
|
@@ -14182,6 +14258,8 @@ function requireHTMLParser () {
|
|
|
14182
14258
|
emitDoctype();
|
|
14183
14259
|
break;
|
|
14184
14260
|
case -1: // EOF
|
|
14261
|
+
// Lookahead states must consume the EOF marker explicitly.
|
|
14262
|
+
nextchar += 1;
|
|
14185
14263
|
forcequirks();
|
|
14186
14264
|
emitDoctype();
|
|
14187
14265
|
emitEOF();
|