happy-dom 17.1.1 → 17.1.3
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/cjs/PropertySymbol.cjs +6 -5
- package/cjs/PropertySymbol.cjs.map +1 -1
- package/cjs/PropertySymbol.d.ts +3 -2
- package/cjs/PropertySymbol.d.ts.map +1 -1
- package/cjs/browser/utilities/BrowserFrameNavigator.cjs +2 -1
- package/cjs/browser/utilities/BrowserFrameNavigator.cjs.map +1 -1
- package/cjs/browser/utilities/BrowserFrameNavigator.d.ts.map +1 -1
- package/cjs/dom/DOMStringMap.cjs +1 -1
- package/cjs/dom/DOMStringMap.cjs.map +1 -1
- package/cjs/exception/DOMExceptionNameEnum.cjs +1 -0
- package/cjs/exception/DOMExceptionNameEnum.cjs.map +1 -1
- package/cjs/exception/DOMExceptionNameEnum.d.ts +2 -1
- package/cjs/exception/DOMExceptionNameEnum.d.ts.map +1 -1
- package/cjs/fetch/AbortController.cjs.map +1 -1
- package/cjs/fetch/AbortController.d.ts +1 -1
- package/cjs/fetch/AbortController.d.ts.map +1 -1
- package/cjs/fetch/AbortSignal.cjs +49 -15
- package/cjs/fetch/AbortSignal.cjs.map +1 -1
- package/cjs/fetch/AbortSignal.d.ts +28 -4
- package/cjs/fetch/AbortSignal.d.ts.map +1 -1
- package/cjs/fetch/Fetch.cjs +8 -5
- package/cjs/fetch/Fetch.cjs.map +1 -1
- package/cjs/fetch/Fetch.d.ts.map +1 -1
- package/cjs/fetch/SyncFetch.cjs +5 -2
- package/cjs/fetch/SyncFetch.cjs.map +1 -1
- package/cjs/fetch/SyncFetch.d.ts.map +1 -1
- package/cjs/html-serializer/HTMLSerializer.cjs +5 -5
- package/cjs/html-serializer/HTMLSerializer.cjs.map +1 -1
- package/cjs/nodes/document/Document.cjs +12 -1
- package/cjs/nodes/document/Document.cjs.map +1 -1
- package/cjs/nodes/document/Document.d.ts.map +1 -1
- package/cjs/nodes/element/Element.cjs +9 -5
- package/cjs/nodes/element/Element.cjs.map +1 -1
- package/cjs/nodes/element/Element.d.ts.map +1 -1
- package/cjs/nodes/element/NamedNodeMap.cjs +34 -26
- package/cjs/nodes/element/NamedNodeMap.cjs.map +1 -1
- package/cjs/nodes/element/NamedNodeMap.d.ts +3 -2
- package/cjs/nodes/element/NamedNodeMap.d.ts.map +1 -1
- package/cjs/nodes/element/NamedNodeMapProxyFactory.cjs +22 -16
- package/cjs/nodes/element/NamedNodeMapProxyFactory.cjs.map +1 -1
- package/cjs/nodes/element/NamedNodeMapProxyFactory.d.ts.map +1 -1
- package/cjs/nodes/html-element/HTMLElement.cjs +10 -7
- package/cjs/nodes/html-element/HTMLElement.cjs.map +1 -1
- package/cjs/nodes/html-element/HTMLElement.d.ts.map +1 -1
- package/cjs/nodes/node/Node.cjs +3 -3
- package/cjs/nodes/node/Node.cjs.map +1 -1
- package/cjs/nodes/node/NodeUtility.cjs +7 -8
- package/cjs/nodes/node/NodeUtility.cjs.map +1 -1
- package/cjs/nodes/node/NodeUtility.d.ts.map +1 -1
- package/cjs/xml-parser/XMLParser.cjs +2 -2
- package/cjs/xml-parser/XMLParser.cjs.map +1 -1
- package/cjs/xml-serializer/XMLSerializer.cjs +5 -8
- package/cjs/xml-serializer/XMLSerializer.cjs.map +1 -1
- package/cjs/xml-serializer/XMLSerializer.d.ts.map +1 -1
- package/lib/PropertySymbol.d.ts +3 -2
- package/lib/PropertySymbol.d.ts.map +1 -1
- package/lib/PropertySymbol.js +3 -2
- package/lib/PropertySymbol.js.map +1 -1
- package/lib/browser/utilities/BrowserFrameNavigator.d.ts.map +1 -1
- package/lib/browser/utilities/BrowserFrameNavigator.js +2 -1
- package/lib/browser/utilities/BrowserFrameNavigator.js.map +1 -1
- package/lib/dom/DOMStringMap.js +1 -1
- package/lib/dom/DOMStringMap.js.map +1 -1
- package/lib/exception/DOMExceptionNameEnum.d.ts +2 -1
- package/lib/exception/DOMExceptionNameEnum.d.ts.map +1 -1
- package/lib/exception/DOMExceptionNameEnum.js +1 -0
- package/lib/exception/DOMExceptionNameEnum.js.map +1 -1
- package/lib/fetch/AbortController.d.ts +1 -1
- package/lib/fetch/AbortController.d.ts.map +1 -1
- package/lib/fetch/AbortController.js.map +1 -1
- package/lib/fetch/AbortSignal.d.ts +28 -4
- package/lib/fetch/AbortSignal.d.ts.map +1 -1
- package/lib/fetch/AbortSignal.js +49 -15
- package/lib/fetch/AbortSignal.js.map +1 -1
- package/lib/fetch/Fetch.d.ts.map +1 -1
- package/lib/fetch/Fetch.js +8 -5
- package/lib/fetch/Fetch.js.map +1 -1
- package/lib/fetch/SyncFetch.d.ts.map +1 -1
- package/lib/fetch/SyncFetch.js +5 -2
- package/lib/fetch/SyncFetch.js.map +1 -1
- package/lib/html-serializer/HTMLSerializer.js +5 -5
- package/lib/html-serializer/HTMLSerializer.js.map +1 -1
- package/lib/nodes/document/Document.d.ts.map +1 -1
- package/lib/nodes/document/Document.js +12 -1
- package/lib/nodes/document/Document.js.map +1 -1
- package/lib/nodes/element/Element.d.ts.map +1 -1
- package/lib/nodes/element/Element.js +9 -5
- package/lib/nodes/element/Element.js.map +1 -1
- package/lib/nodes/element/NamedNodeMap.d.ts +3 -2
- package/lib/nodes/element/NamedNodeMap.d.ts.map +1 -1
- package/lib/nodes/element/NamedNodeMap.js +34 -26
- package/lib/nodes/element/NamedNodeMap.js.map +1 -1
- package/lib/nodes/element/NamedNodeMapProxyFactory.d.ts.map +1 -1
- package/lib/nodes/element/NamedNodeMapProxyFactory.js +22 -16
- package/lib/nodes/element/NamedNodeMapProxyFactory.js.map +1 -1
- package/lib/nodes/html-element/HTMLElement.d.ts.map +1 -1
- package/lib/nodes/html-element/HTMLElement.js +10 -7
- package/lib/nodes/html-element/HTMLElement.js.map +1 -1
- package/lib/nodes/node/Node.js +3 -3
- package/lib/nodes/node/Node.js.map +1 -1
- package/lib/nodes/node/NodeUtility.d.ts.map +1 -1
- package/lib/nodes/node/NodeUtility.js +7 -8
- package/lib/nodes/node/NodeUtility.js.map +1 -1
- package/lib/xml-parser/XMLParser.js +2 -2
- package/lib/xml-parser/XMLParser.js.map +1 -1
- package/lib/xml-serializer/XMLSerializer.d.ts.map +1 -1
- package/lib/xml-serializer/XMLSerializer.js +5 -8
- package/lib/xml-serializer/XMLSerializer.js.map +1 -1
- package/package.json +1 -1
- package/src/PropertySymbol.ts +3 -2
- package/src/browser/utilities/BrowserFrameNavigator.ts +8 -1
- package/src/dom/DOMStringMap.ts +1 -1
- package/src/exception/DOMExceptionNameEnum.ts +2 -1
- package/src/fetch/AbortController.ts +1 -1
- package/src/fetch/AbortSignal.ts +61 -25
- package/src/fetch/Fetch.ts +10 -7
- package/src/fetch/SyncFetch.ts +6 -3
- package/src/html-serializer/HTMLSerializer.ts +5 -5
- package/src/nodes/document/Document.ts +22 -1
- package/src/nodes/element/Element.ts +20 -5
- package/src/nodes/element/NamedNodeMap.ts +42 -27
- package/src/nodes/element/NamedNodeMapProxyFactory.ts +22 -17
- package/src/nodes/html-element/HTMLElement.ts +11 -10
- package/src/nodes/node/Node.ts +5 -5
- package/src/nodes/node/NodeUtility.ts +7 -8
- package/src/xml-parser/XMLParser.ts +2 -2
- package/src/xml-serializer/XMLSerializer.ts +9 -12
package/src/fetch/AbortSignal.ts
CHANGED
@@ -14,9 +14,9 @@ export default class AbortSignal extends EventTarget {
|
|
14
14
|
protected declare static [PropertySymbol.window]: BrowserWindow;
|
15
15
|
protected declare [PropertySymbol.window]: BrowserWindow;
|
16
16
|
|
17
|
-
//
|
18
|
-
public
|
19
|
-
public
|
17
|
+
// Internal properties
|
18
|
+
public [PropertySymbol.aborted]: boolean = false;
|
19
|
+
public [PropertySymbol.reason]: any = undefined;
|
20
20
|
|
21
21
|
// Events
|
22
22
|
public onabort: ((this: AbortSignal, event: Event) => void) | null = null;
|
@@ -28,9 +28,7 @@ export default class AbortSignal extends EventTarget {
|
|
28
28
|
super();
|
29
29
|
|
30
30
|
if (!this[PropertySymbol.window]) {
|
31
|
-
throw new TypeError(
|
32
|
-
`Failed to construct '${this.constructor.name}': '${this.constructor.name}' was constructed outside a Window context.`
|
33
|
-
);
|
31
|
+
throw new TypeError(`Failed to construct 'AbortSignal': Illegal constructor`);
|
34
32
|
}
|
35
33
|
}
|
36
34
|
|
@@ -41,22 +39,59 @@ export default class AbortSignal extends EventTarget {
|
|
41
39
|
return 'AbortSignal';
|
42
40
|
}
|
43
41
|
|
42
|
+
/**
|
43
|
+
* Returns true if the signal has been aborted.
|
44
|
+
*
|
45
|
+
* @returns True if the signal has been aborted.
|
46
|
+
*/
|
47
|
+
public get aborted(): boolean {
|
48
|
+
return this[PropertySymbol.aborted];
|
49
|
+
}
|
50
|
+
|
51
|
+
/**
|
52
|
+
* Setter for aborted. Value will be ignored as the property is read-only.
|
53
|
+
*
|
54
|
+
* @param _value Aborted.
|
55
|
+
*/
|
56
|
+
public set aborted(_value: boolean) {
|
57
|
+
// Do nothing
|
58
|
+
}
|
59
|
+
|
60
|
+
/**
|
61
|
+
* Returns the reason the signal was aborted.
|
62
|
+
*
|
63
|
+
* @returns Reason.
|
64
|
+
*/
|
65
|
+
public get reason(): any {
|
66
|
+
return this[PropertySymbol.reason];
|
67
|
+
}
|
68
|
+
|
69
|
+
/**
|
70
|
+
* Setter for reason. Value will be ignored as the property is read-only.
|
71
|
+
*
|
72
|
+
* @param _value Reason.
|
73
|
+
*/
|
74
|
+
public set reason(_value: any) {
|
75
|
+
// Do nothing
|
76
|
+
}
|
77
|
+
|
44
78
|
/**
|
45
79
|
* Aborts the signal.
|
46
80
|
*
|
47
81
|
* @param [reason] Reason.
|
48
82
|
*/
|
49
|
-
public [PropertySymbol.abort](reason?:
|
83
|
+
public [PropertySymbol.abort](reason?: any): void {
|
50
84
|
if (this.aborted) {
|
51
85
|
return;
|
52
86
|
}
|
53
|
-
|
54
|
-
reason
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
87
|
+
this[PropertySymbol.reason] =
|
88
|
+
reason !== undefined
|
89
|
+
? reason
|
90
|
+
: new this[PropertySymbol.window].DOMException(
|
91
|
+
'signal is aborted without reason',
|
92
|
+
DOMExceptionNameEnum.abortError
|
93
|
+
);
|
94
|
+
this[PropertySymbol.aborted] = true;
|
60
95
|
this.dispatchEvent(new Event('abort'));
|
61
96
|
}
|
62
97
|
|
@@ -75,15 +110,16 @@ export default class AbortSignal extends EventTarget {
|
|
75
110
|
* @param [reason] Reason.
|
76
111
|
* @returns AbortSignal instance.
|
77
112
|
*/
|
78
|
-
public static abort(reason?:
|
113
|
+
public static abort(reason?: any): AbortSignal {
|
79
114
|
const signal = new this();
|
80
|
-
|
81
|
-
reason
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
115
|
+
signal[PropertySymbol.reason] =
|
116
|
+
reason !== undefined
|
117
|
+
? reason
|
118
|
+
: new this[PropertySymbol.window].DOMException(
|
119
|
+
'signal is aborted without reason',
|
120
|
+
DOMExceptionNameEnum.abortError
|
121
|
+
);
|
122
|
+
signal[PropertySymbol.aborted] = true;
|
87
123
|
return signal;
|
88
124
|
}
|
89
125
|
|
@@ -118,8 +154,8 @@ export default class AbortSignal extends EventTarget {
|
|
118
154
|
*/
|
119
155
|
public static any(signals: AbortSignal[]): AbortSignal {
|
120
156
|
for (const signal of signals) {
|
121
|
-
if (signal.aborted) {
|
122
|
-
return this.abort(signal.reason);
|
157
|
+
if (signal[PropertySymbol.aborted]) {
|
158
|
+
return this.abort(signal[PropertySymbol.reason]);
|
123
159
|
}
|
124
160
|
}
|
125
161
|
|
@@ -135,7 +171,7 @@ export default class AbortSignal extends EventTarget {
|
|
135
171
|
for (const signal of signals) {
|
136
172
|
const handler = (): void => {
|
137
173
|
stopListening();
|
138
|
-
anySignal[PropertySymbol.abort](signal.reason);
|
174
|
+
anySignal[PropertySymbol.abort](signal[PropertySymbol.reason]);
|
139
175
|
};
|
140
176
|
handlers.set(signal, handler);
|
141
177
|
signal.addEventListener('abort', handler);
|
package/src/fetch/Fetch.ts
CHANGED
@@ -134,9 +134,12 @@ export default class Fetch {
|
|
134
134
|
|
135
135
|
FetchRequestValidationUtility.validateSchema(this.request);
|
136
136
|
|
137
|
-
if (this.request.signal.aborted) {
|
138
|
-
|
139
|
-
|
137
|
+
if (this.request.signal[PropertySymbol.aborted]) {
|
138
|
+
if (this.request.signal[PropertySymbol.reason] !== undefined) {
|
139
|
+
throw this.request.signal[PropertySymbol.reason];
|
140
|
+
}
|
141
|
+
throw new this[PropertySymbol.window].DOMException(
|
142
|
+
'signal is aborted without reason',
|
140
143
|
DOMExceptionNameEnum.abortError
|
141
144
|
);
|
142
145
|
}
|
@@ -947,8 +950,8 @@ export default class Fetch {
|
|
947
950
|
headers.delete('cookie2');
|
948
951
|
}
|
949
952
|
|
950
|
-
if (this.request.signal.aborted) {
|
951
|
-
this.abort();
|
953
|
+
if (this.request.signal[PropertySymbol.aborted]) {
|
954
|
+
this.abort(this.request.signal[PropertySymbol.reason]);
|
952
955
|
return true;
|
953
956
|
}
|
954
957
|
|
@@ -1006,7 +1009,7 @@ export default class Fetch {
|
|
1006
1009
|
*
|
1007
1010
|
* @param reason Reason.
|
1008
1011
|
*/
|
1009
|
-
private abort(reason?:
|
1012
|
+
private abort(reason?: any): void {
|
1010
1013
|
const error = new this.#window.DOMException(
|
1011
1014
|
'The operation was aborted.' + (reason ? ' ' + reason.toString() : ''),
|
1012
1015
|
DOMExceptionNameEnum.abortError
|
@@ -1034,7 +1037,7 @@ export default class Fetch {
|
|
1034
1037
|
}
|
1035
1038
|
|
1036
1039
|
if (this.reject) {
|
1037
|
-
this.reject(error);
|
1040
|
+
this.reject(reason !== undefined ? reason : error);
|
1038
1041
|
}
|
1039
1042
|
}
|
1040
1043
|
}
|
package/src/fetch/SyncFetch.ts
CHANGED
@@ -113,9 +113,12 @@ export default class SyncFetch {
|
|
113
113
|
|
114
114
|
FetchRequestValidationUtility.validateSchema(this.request);
|
115
115
|
|
116
|
-
if (this.request.signal.aborted) {
|
117
|
-
|
118
|
-
|
116
|
+
if (this.request.signal[PropertySymbol.aborted]) {
|
117
|
+
if (this.request.signal[PropertySymbol.reason] !== undefined) {
|
118
|
+
throw this.request.signal[PropertySymbol.reason];
|
119
|
+
}
|
120
|
+
throw new this[PropertySymbol.window].DOMException(
|
121
|
+
'signal is aborted without reason',
|
119
122
|
DOMExceptionNameEnum.abortError
|
120
123
|
);
|
121
124
|
}
|
@@ -143,18 +143,18 @@ export default class HTMLSerializer {
|
|
143
143
|
private getAttributes(element: Element): string {
|
144
144
|
let attributeString = '';
|
145
145
|
|
146
|
-
const
|
146
|
+
const attributes = (<Element>element)[PropertySymbol.attributes][PropertySymbol.items];
|
147
147
|
|
148
|
-
if (!
|
148
|
+
if (!attributes.has(':is') && element[PropertySymbol.isValue]) {
|
149
149
|
attributeString +=
|
150
150
|
' is="' + XMLEncodeUtility.encodeHTMLAttributeValue(element[PropertySymbol.isValue]) + '"';
|
151
151
|
}
|
152
152
|
|
153
|
-
for (const
|
153
|
+
for (const attribute of attributes.values()) {
|
154
154
|
const escapedValue = XMLEncodeUtility.encodeHTMLAttributeValue(
|
155
|
-
|
155
|
+
attribute[PropertySymbol.value]
|
156
156
|
);
|
157
|
-
attributeString += ' ' +
|
157
|
+
attributeString += ' ' + attribute[PropertySymbol.name] + '="' + escapedValue + '"';
|
158
158
|
}
|
159
159
|
|
160
160
|
return attributeString;
|
@@ -50,6 +50,7 @@ import SVGElementConfig from '../../config/SVGElementConfig.js';
|
|
50
50
|
import StringUtility from '../../utilities/StringUtility.js';
|
51
51
|
import HTMLParser from '../../html-parser/HTMLParser.js';
|
52
52
|
import PreloadEntry from '../../fetch/preload/PreloadEntry.js';
|
53
|
+
import DOMExceptionNameEnum from '../../exception/DOMExceptionNameEnum.js';
|
53
54
|
|
54
55
|
const PROCESSING_INSTRUCTION_TARGET_REGEXP = /^[a-z][a-z0-9-]+$/;
|
55
56
|
|
@@ -1222,7 +1223,17 @@ export default class Document extends Node {
|
|
1222
1223
|
* @returns Attribute.
|
1223
1224
|
*/
|
1224
1225
|
public createAttribute(qualifiedName: string): Attr {
|
1225
|
-
|
1226
|
+
// We should use the NodeFactory and not the class constructor, so that owner document will be this document
|
1227
|
+
const attribute = NodeFactory.createNode(this, this[PropertySymbol.window].Attr);
|
1228
|
+
|
1229
|
+
const name = StringUtility.asciiLowerCase(qualifiedName);
|
1230
|
+
const parts = name.split(':');
|
1231
|
+
|
1232
|
+
attribute[PropertySymbol.name] = name;
|
1233
|
+
attribute[PropertySymbol.localName] = parts[1] ?? name;
|
1234
|
+
attribute[PropertySymbol.prefix] = parts[1] ? parts[0] : null;
|
1235
|
+
|
1236
|
+
return attribute;
|
1226
1237
|
}
|
1227
1238
|
|
1228
1239
|
/**
|
@@ -1237,11 +1248,21 @@ export default class Document extends Node {
|
|
1237
1248
|
const attribute = NodeFactory.createNode(this, this[PropertySymbol.window].Attr);
|
1238
1249
|
|
1239
1250
|
const parts = qualifiedName.split(':');
|
1251
|
+
|
1240
1252
|
attribute[PropertySymbol.namespaceURI] = namespaceURI;
|
1241
1253
|
attribute[PropertySymbol.name] = qualifiedName;
|
1242
1254
|
attribute[PropertySymbol.localName] = parts[1] ?? qualifiedName;
|
1243
1255
|
attribute[PropertySymbol.prefix] = parts[1] ? parts[0] : null;
|
1244
1256
|
|
1257
|
+
if (!namespaceURI && attribute[PropertySymbol.prefix]) {
|
1258
|
+
throw new this[PropertySymbol.window].DOMException(
|
1259
|
+
`Failed to execute 'createAttributeNS' on 'Document': The namespace URI provided ('${
|
1260
|
+
namespaceURI || ''
|
1261
|
+
}') is not valid for the qualified name provided ('${qualifiedName}').`,
|
1262
|
+
DOMExceptionNameEnum.namespaceError
|
1263
|
+
);
|
1264
|
+
}
|
1265
|
+
|
1245
1266
|
return attribute;
|
1246
1267
|
}
|
1247
1268
|
|
@@ -33,6 +33,7 @@ import HTMLSerializer from '../../html-serializer/HTMLSerializer.js';
|
|
33
33
|
import HTMLParser from '../../html-parser/HTMLParser.js';
|
34
34
|
import IScrollToOptions from '../../window/IScrollToOptions.js';
|
35
35
|
import { AttributeUtility } from '../../utilities/AttributeUtility.js';
|
36
|
+
import DOMExceptionNameEnum from '../../exception/DOMExceptionNameEnum.js';
|
36
37
|
|
37
38
|
type InsertAdjacentPosition = 'beforebegin' | 'afterbegin' | 'beforeend' | 'afterend';
|
38
39
|
|
@@ -545,9 +546,17 @@ export default class Element
|
|
545
546
|
clone[PropertySymbol.shadowRoot][PropertySymbol.host] = clone;
|
546
547
|
}
|
547
548
|
|
548
|
-
|
549
|
-
|
550
|
-
|
549
|
+
clone[PropertySymbol.attributes][PropertySymbol.itemsByNamespaceURI] = new Map(
|
550
|
+
this[PropertySymbol.attributes][PropertySymbol.itemsByNamespaceURI]
|
551
|
+
);
|
552
|
+
|
553
|
+
clone[PropertySymbol.attributes][PropertySymbol.itemsByName] = new Map(
|
554
|
+
this[PropertySymbol.attributes][PropertySymbol.itemsByName]
|
555
|
+
);
|
556
|
+
|
557
|
+
clone[PropertySymbol.attributes][PropertySymbol.items] = new Map(
|
558
|
+
this[PropertySymbol.attributes][PropertySymbol.items]
|
559
|
+
);
|
551
560
|
|
552
561
|
return <Element>clone;
|
553
562
|
}
|
@@ -704,6 +713,12 @@ export default class Element
|
|
704
713
|
*/
|
705
714
|
public setAttributeNS(namespaceURI: string, name: string, value: string): void {
|
706
715
|
const attribute = this[PropertySymbol.ownerDocument].createAttributeNS(namespaceURI, name);
|
716
|
+
if (!namespaceURI && attribute[PropertySymbol.prefix]) {
|
717
|
+
throw new this[PropertySymbol.window].DOMException(
|
718
|
+
`Failed to execute 'setAttributeNS' on 'Element': '' is an invalid namespace for attributes.`,
|
719
|
+
DOMExceptionNameEnum.namespaceError
|
720
|
+
);
|
721
|
+
}
|
707
722
|
attribute[PropertySymbol.value] = String(value);
|
708
723
|
this[PropertySymbol.attributes].setNamedItemNS(attribute);
|
709
724
|
}
|
@@ -715,7 +730,7 @@ export default class Element
|
|
715
730
|
*/
|
716
731
|
public getAttributeNames(): string[] {
|
717
732
|
const names = [];
|
718
|
-
for (const item of this[PropertySymbol.attributes][PropertySymbol.
|
733
|
+
for (const item of this[PropertySymbol.attributes][PropertySymbol.items].values()) {
|
719
734
|
names.push(item[PropertySymbol.name]);
|
720
735
|
}
|
721
736
|
return names;
|
@@ -799,7 +814,7 @@ export default class Element
|
|
799
814
|
* @returns "true" if the element has attributes.
|
800
815
|
*/
|
801
816
|
public hasAttributes(): boolean {
|
802
|
-
return this[PropertySymbol.attributes][PropertySymbol.
|
817
|
+
return this[PropertySymbol.attributes][PropertySymbol.items].size > 0;
|
803
818
|
}
|
804
819
|
|
805
820
|
/**
|
@@ -14,11 +14,14 @@ import StringUtility from '../../utilities/StringUtility.js';
|
|
14
14
|
export default class NamedNodeMap {
|
15
15
|
[index: number]: Attr;
|
16
16
|
|
17
|
-
//
|
18
|
-
public [PropertySymbol.
|
17
|
+
// Items by attribute namespaceURI
|
18
|
+
public [PropertySymbol.itemsByNamespaceURI]: Map<string, Attr> = new Map();
|
19
19
|
|
20
|
-
// Items
|
21
|
-
public [PropertySymbol.
|
20
|
+
// Items by attribute name
|
21
|
+
public [PropertySymbol.itemsByName]: Map<string, Attr[]> = new Map();
|
22
|
+
|
23
|
+
// All items
|
24
|
+
public [PropertySymbol.items]: Map<string, Attr> = new Map();
|
22
25
|
|
23
26
|
public declare [PropertySymbol.ownerElement]: Element;
|
24
27
|
|
@@ -37,7 +40,7 @@ export default class NamedNodeMap {
|
|
37
40
|
* @returns Length.
|
38
41
|
*/
|
39
42
|
public get length(): number {
|
40
|
-
return this[PropertySymbol.
|
43
|
+
return this[PropertySymbol.items].size;
|
41
44
|
}
|
42
45
|
|
43
46
|
/**
|
@@ -64,7 +67,7 @@ export default class NamedNodeMap {
|
|
64
67
|
* @returns Iterator.
|
65
68
|
*/
|
66
69
|
public [Symbol.iterator](): IterableIterator<Attr> {
|
67
|
-
return this[PropertySymbol.
|
70
|
+
return this[PropertySymbol.items].values();
|
68
71
|
}
|
69
72
|
|
70
73
|
/**
|
@@ -73,7 +76,7 @@ export default class NamedNodeMap {
|
|
73
76
|
* @param index Index.
|
74
77
|
*/
|
75
78
|
public item(index: number): Attr | null {
|
76
|
-
const items = Array.from(this[PropertySymbol.
|
79
|
+
const items = Array.from(this[PropertySymbol.items].values());
|
77
80
|
return index >= 0 && items[index] ? items[index] : null;
|
78
81
|
}
|
79
82
|
|
@@ -91,9 +94,9 @@ export default class NamedNodeMap {
|
|
91
94
|
PropertySymbol.contentType
|
92
95
|
] === 'text/html'
|
93
96
|
) {
|
94
|
-
return this[PropertySymbol.
|
97
|
+
return this[PropertySymbol.itemsByName].get(StringUtility.asciiLowerCase(name))?.[0] || null;
|
95
98
|
}
|
96
|
-
return this[PropertySymbol.
|
99
|
+
return this[PropertySymbol.itemsByName].get(name)?.[0] || null;
|
97
100
|
}
|
98
101
|
|
99
102
|
/**
|
@@ -104,11 +107,17 @@ export default class NamedNodeMap {
|
|
104
107
|
* @returns Item.
|
105
108
|
*/
|
106
109
|
public getNamedItemNS(namespace: string, localName: string): Attr | null {
|
107
|
-
|
108
|
-
|
110
|
+
const item = this[PropertySymbol.itemsByNamespaceURI].get(`${namespace || ''}:${localName}`);
|
111
|
+
|
112
|
+
// It seems like an item cant have a prefix without a namespaceURI
|
113
|
+
// E.g. element.setAttribute('ns1:key', 'value1');
|
114
|
+
// expect(element.attributes.getNamedItemNS(null, 'key')).toBeNull();
|
115
|
+
|
116
|
+
if (item && (!item[PropertySymbol.prefix] || item[PropertySymbol.namespaceURI])) {
|
117
|
+
return item;
|
109
118
|
}
|
110
119
|
|
111
|
-
return
|
120
|
+
return null;
|
112
121
|
}
|
113
122
|
|
114
123
|
/**
|
@@ -199,26 +208,29 @@ export default class NamedNodeMap {
|
|
199
208
|
const replacedItem =
|
200
209
|
this.getNamedItemNS(item[PropertySymbol.namespaceURI], item[PropertySymbol.localName]) ||
|
201
210
|
null;
|
202
|
-
|
203
|
-
const namedItems = this[PropertySymbol.namedItems].get(item[PropertySymbol.name]);
|
211
|
+
const itemsByName = this[PropertySymbol.itemsByName].get(item[PropertySymbol.name]);
|
204
212
|
|
205
213
|
if (replacedItem === item) {
|
206
214
|
return item;
|
207
215
|
}
|
208
216
|
|
209
|
-
this[PropertySymbol.
|
217
|
+
this[PropertySymbol.itemsByNamespaceURI].set(
|
210
218
|
`${item[PropertySymbol.namespaceURI] || ''}:${item[PropertySymbol.localName]}`,
|
211
219
|
item
|
212
220
|
);
|
221
|
+
this[PropertySymbol.items].set(
|
222
|
+
`${item[PropertySymbol.namespaceURI] || ''}:${item[PropertySymbol.name]}`,
|
223
|
+
item
|
224
|
+
);
|
213
225
|
|
214
|
-
if (!
|
215
|
-
this[PropertySymbol.
|
226
|
+
if (!itemsByName?.length) {
|
227
|
+
this[PropertySymbol.itemsByName].set(item[PropertySymbol.name], [item]);
|
216
228
|
} else {
|
217
|
-
const index =
|
229
|
+
const index = itemsByName.indexOf(replacedItem);
|
218
230
|
if (index !== -1) {
|
219
|
-
|
231
|
+
itemsByName.splice(index, 1);
|
220
232
|
}
|
221
|
-
|
233
|
+
itemsByName.push(item);
|
222
234
|
}
|
223
235
|
|
224
236
|
if (!ignoreListeners) {
|
@@ -237,19 +249,22 @@ export default class NamedNodeMap {
|
|
237
249
|
public [PropertySymbol.removeNamedItem](item: Attr, ignoreListeners = false): void {
|
238
250
|
item[PropertySymbol.ownerElement] = null;
|
239
251
|
|
240
|
-
this[PropertySymbol.
|
252
|
+
this[PropertySymbol.itemsByNamespaceURI].delete(
|
241
253
|
`${item[PropertySymbol.namespaceURI] || ''}:${item[PropertySymbol.localName]}`
|
242
254
|
);
|
255
|
+
this[PropertySymbol.items].delete(
|
256
|
+
`${item[PropertySymbol.namespaceURI] || ''}:${item[PropertySymbol.name]}`
|
257
|
+
);
|
243
258
|
|
244
|
-
const
|
259
|
+
const itemsByName = this[PropertySymbol.itemsByName].get(item[PropertySymbol.name]);
|
245
260
|
|
246
|
-
if (
|
247
|
-
const index =
|
261
|
+
if (itemsByName?.length) {
|
262
|
+
const index = itemsByName.indexOf(item);
|
248
263
|
if (index !== -1) {
|
249
|
-
|
264
|
+
itemsByName.splice(index, 1);
|
250
265
|
}
|
251
|
-
if (!
|
252
|
-
this[PropertySymbol.
|
266
|
+
if (!itemsByName.length) {
|
267
|
+
this[PropertySymbol.itemsByName].delete(item[PropertySymbol.name]);
|
253
268
|
}
|
254
269
|
}
|
255
270
|
|
@@ -21,7 +21,7 @@ export default class NamedNodeMapProxyFactory {
|
|
21
21
|
return new Proxy<NamedNodeMap>(namedNodeMap, {
|
22
22
|
get: (target, property) => {
|
23
23
|
if (property === 'length') {
|
24
|
-
return namedNodeMap[PropertySymbol.
|
24
|
+
return namedNodeMap[PropertySymbol.items].size;
|
25
25
|
}
|
26
26
|
if (property in target || typeof property === 'symbol') {
|
27
27
|
methodBinder.bind(property);
|
@@ -29,7 +29,7 @@ export default class NamedNodeMapProxyFactory {
|
|
29
29
|
}
|
30
30
|
const index = Number(property);
|
31
31
|
if (!isNaN(index)) {
|
32
|
-
return
|
32
|
+
return target.item(index);
|
33
33
|
}
|
34
34
|
return target.getNamedItem(<string>property) || undefined;
|
35
35
|
},
|
@@ -57,8 +57,8 @@ export default class NamedNodeMapProxyFactory {
|
|
57
57
|
return true;
|
58
58
|
},
|
59
59
|
ownKeys(): string[] {
|
60
|
-
const keys = Array.from(namedNodeMap[PropertySymbol.
|
61
|
-
for (let i = 0, max = namedNodeMap[PropertySymbol.
|
60
|
+
const keys = Array.from(namedNodeMap[PropertySymbol.items].keys());
|
61
|
+
for (let i = 0, max = namedNodeMap[PropertySymbol.items].size; i < max; i++) {
|
62
62
|
keys.push(String(i));
|
63
63
|
}
|
64
64
|
return keys;
|
@@ -68,13 +68,13 @@ export default class NamedNodeMapProxyFactory {
|
|
68
68
|
return false;
|
69
69
|
}
|
70
70
|
|
71
|
-
if (property in target || namedNodeMap[PropertySymbol.
|
71
|
+
if (property in target || namedNodeMap[PropertySymbol.items].has(property)) {
|
72
72
|
return true;
|
73
73
|
}
|
74
74
|
|
75
75
|
const index = Number(property);
|
76
76
|
|
77
|
-
if (!isNaN(index) && index >= 0 && index < namedNodeMap[PropertySymbol.
|
77
|
+
if (!isNaN(index) && index >= 0 && index < namedNodeMap[PropertySymbol.items].size) {
|
78
78
|
return true;
|
79
79
|
}
|
80
80
|
|
@@ -96,21 +96,26 @@ export default class NamedNodeMapProxyFactory {
|
|
96
96
|
}
|
97
97
|
|
98
98
|
const index = Number(property);
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
99
|
+
if (!isNaN(index)) {
|
100
|
+
if (index >= 0) {
|
101
|
+
const itemByIndex = target.item(index);
|
102
|
+
if (itemByIndex) {
|
103
|
+
return {
|
104
|
+
value: itemByIndex,
|
105
|
+
writable: false,
|
106
|
+
enumerable: true,
|
107
|
+
configurable: true
|
108
|
+
};
|
109
|
+
}
|
110
|
+
}
|
111
|
+
return;
|
107
112
|
}
|
108
113
|
|
109
|
-
const
|
114
|
+
const items = namedNodeMap[PropertySymbol.items].get(<string>property);
|
110
115
|
|
111
|
-
if (
|
116
|
+
if (items) {
|
112
117
|
return {
|
113
|
-
value:
|
118
|
+
value: items,
|
114
119
|
writable: false,
|
115
120
|
enumerable: true,
|
116
121
|
configurable: true
|
@@ -649,14 +649,14 @@ export default class HTMLElement extends Element {
|
|
649
649
|
newElement[PropertySymbol.isValue] = this[PropertySymbol.isValue];
|
650
650
|
newElement[PropertySymbol.cache] = this[PropertySymbol.cache];
|
651
651
|
newElement[PropertySymbol.affectsCache] = this[PropertySymbol.affectsCache];
|
652
|
-
newElement[PropertySymbol.attributes][PropertySymbol.
|
653
|
-
this[PropertySymbol.attributes][PropertySymbol.
|
654
|
-
newElement[PropertySymbol.attributes][PropertySymbol.
|
655
|
-
this[PropertySymbol.attributes][PropertySymbol.
|
656
|
-
|
657
|
-
|
658
|
-
|
659
|
-
].values()) {
|
652
|
+
newElement[PropertySymbol.attributes][PropertySymbol.itemsByNamespaceURI] =
|
653
|
+
this[PropertySymbol.attributes][PropertySymbol.itemsByNamespaceURI];
|
654
|
+
newElement[PropertySymbol.attributes][PropertySymbol.itemsByName] =
|
655
|
+
this[PropertySymbol.attributes][PropertySymbol.itemsByName];
|
656
|
+
newElement[PropertySymbol.attributes][PropertySymbol.items] =
|
657
|
+
this[PropertySymbol.attributes][PropertySymbol.items];
|
658
|
+
|
659
|
+
for (const attr of newElement[PropertySymbol.attributes][PropertySymbol.items].values()) {
|
660
660
|
attr[PropertySymbol.ownerElement] = newElement;
|
661
661
|
}
|
662
662
|
|
@@ -677,8 +677,9 @@ export default class HTMLElement extends Element {
|
|
677
677
|
this[PropertySymbol.isValue] = null;
|
678
678
|
this[PropertySymbol.cache] = newCache;
|
679
679
|
this[PropertySymbol.affectsCache] = [];
|
680
|
-
this[PropertySymbol.attributes][PropertySymbol.
|
681
|
-
this[PropertySymbol.attributes][PropertySymbol.
|
680
|
+
this[PropertySymbol.attributes][PropertySymbol.itemsByNamespaceURI] = new Map();
|
681
|
+
this[PropertySymbol.attributes][PropertySymbol.itemsByName] = new Map();
|
682
|
+
this[PropertySymbol.attributes][PropertySymbol.items] = new Map();
|
682
683
|
|
683
684
|
for (const node of newElement[PropertySymbol.nodeArray]) {
|
684
685
|
node[PropertySymbol.parentNode] = newElement;
|
package/src/nodes/node/Node.ts
CHANGED
@@ -1102,13 +1102,13 @@ export default class Node extends EventTarget {
|
|
1102
1102
|
/**
|
1103
1103
|
* 5.2.1. For each attr in node2’s attribute list:
|
1104
1104
|
*/
|
1105
|
-
for (const
|
1106
|
-
|
1107
|
-
)) {
|
1105
|
+
for (const attribute of (<Element>node2)[PropertySymbol.attributes][
|
1106
|
+
PropertySymbol.items
|
1107
|
+
].values()) {
|
1108
1108
|
/**
|
1109
1109
|
* 5.2.1.1. If attr equals attr1, then return the result of adding DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC and DOCUMENT_POSITION_PRECEDING.
|
1110
1110
|
*/
|
1111
|
-
if (NodeUtility.isEqualNode(
|
1111
|
+
if (NodeUtility.isEqualNode(attribute, attr1)) {
|
1112
1112
|
return (
|
1113
1113
|
Node.DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC | Node.DOCUMENT_POSITION_PRECEDING
|
1114
1114
|
);
|
@@ -1117,7 +1117,7 @@ export default class Node extends EventTarget {
|
|
1117
1117
|
/**
|
1118
1118
|
* 5.2.1.2. If attr equals attr2, then return the result of adding DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC and DOCUMENT_POSITION_FOLLOWING.
|
1119
1119
|
*/
|
1120
|
-
if (NodeUtility.isEqualNode(
|
1120
|
+
if (NodeUtility.isEqualNode(attribute, attr2)) {
|
1121
1121
|
return (
|
1122
1122
|
Node.DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC | Node.DOCUMENT_POSITION_FOLLOWING
|
1123
1123
|
);
|
@@ -200,19 +200,18 @@ export default class NodeUtility {
|
|
200
200
|
*/
|
201
201
|
public static attributeListsEqual(elementA: Element, elementB: Element): boolean {
|
202
202
|
const attributesA = Array.from(
|
203
|
-
elementA[PropertySymbol.attributes][PropertySymbol.
|
203
|
+
elementA[PropertySymbol.attributes][PropertySymbol.items].values()
|
204
204
|
);
|
205
205
|
const attributesB = Array.from(
|
206
|
-
elementB[PropertySymbol.attributes][PropertySymbol.
|
206
|
+
elementB[PropertySymbol.attributes][PropertySymbol.items].values()
|
207
207
|
);
|
208
208
|
for (const attributeA of attributesA) {
|
209
209
|
let found = false;
|
210
210
|
for (const attributeB of attributesB) {
|
211
211
|
if (
|
212
|
-
attributeA[
|
213
|
-
|
214
|
-
attributeA[
|
215
|
-
attributeA[0][PropertySymbol.value] === attributeB[0][PropertySymbol.value]
|
212
|
+
attributeA[PropertySymbol.namespaceURI] === attributeB[PropertySymbol.namespaceURI] &&
|
213
|
+
attributeA.localName === attributeB.localName &&
|
214
|
+
attributeA[PropertySymbol.value] === attributeB[PropertySymbol.value]
|
216
215
|
) {
|
217
216
|
found = true;
|
218
217
|
break;
|
@@ -258,8 +257,8 @@ export default class NodeUtility {
|
|
258
257
|
elementA[PropertySymbol.namespaceURI] !== elementB[PropertySymbol.namespaceURI] ||
|
259
258
|
elementA[PropertySymbol.prefix] !== elementB[PropertySymbol.prefix] ||
|
260
259
|
elementA[PropertySymbol.localName] !== elementB[PropertySymbol.localName] ||
|
261
|
-
elementA[PropertySymbol.attributes][PropertySymbol.
|
262
|
-
elementB[PropertySymbol.attributes][PropertySymbol.
|
260
|
+
elementA[PropertySymbol.attributes][PropertySymbol.items].size !==
|
261
|
+
elementB[PropertySymbol.attributes][PropertySymbol.items].size
|
263
262
|
) {
|
264
263
|
return false;
|
265
264
|
}
|
@@ -533,8 +533,8 @@ export default class XMLParser {
|
|
533
533
|
);
|
534
534
|
this.nextElement[PropertySymbol.attributes] = attributes;
|
535
535
|
attributes[PropertySymbol.ownerElement] = this.nextElement;
|
536
|
-
for (const
|
537
|
-
|
536
|
+
for (const item of attributes[PropertySymbol.items].values()) {
|
537
|
+
item[PropertySymbol.ownerElement] = this.nextElement;
|
538
538
|
}
|
539
539
|
} else {
|
540
540
|
this.nextElement[PropertySymbol.namespaceURI] = value;
|